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(arg,buffer,lenremain)140 kg_seqstate_externalize(arg, buffer, lenremain)
141 g_seqnum_state arg;
142 krb5_octet **buffer;
143 size_t *lenremain;
144 {
145 krb5_error_code err;
146 err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
147 if (err == 0)
148 err = g_seqstate_externalize(arg, buffer, lenremain);
149 if (err == 0)
150 err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
151 return err;
152 }
153
154 static krb5_error_code
kg_seqstate_internalize(argp,buffer,lenremain)155 kg_seqstate_internalize(argp, buffer, lenremain)
156 g_seqnum_state *argp;
157 krb5_octet **buffer;
158 size_t *lenremain;
159 {
160 krb5_int32 ibuf;
161 krb5_octet *bp;
162 size_t remain;
163 krb5_error_code err;
164
165 bp = *buffer;
166 remain = *lenremain;
167
168 /* Read in and check our magic number */
169 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
170 return (EINVAL);
171
172 if (ibuf != KV5M_GSS_QUEUE)
173 return (EINVAL);
174
175 err = g_seqstate_internalize(argp, &bp, &remain);
176 if (err)
177 return err;
178
179 /* Read in and check our trailing magic number */
180 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
181 g_seqstate_free(*argp);
182 return (EINVAL);
183 }
184
185 if (ibuf != KV5M_GSS_QUEUE) {
186 g_seqstate_free(*argp);
187 return (EINVAL);
188 }
189
190 *buffer = bp;
191 *lenremain = remain;
192 return 0;
193 }
194
195 static krb5_error_code
kg_seqstate_size(arg,sizep)196 kg_seqstate_size(arg, sizep)
197 g_seqnum_state arg;
198 size_t *sizep;
199 {
200 krb5_error_code kret;
201 size_t required;
202
203 kret = EINVAL;
204 if (arg) {
205 required = 2*sizeof(krb5_int32); /* For the header and trailer */
206 g_seqstate_size(arg, &required);
207
208 kret = 0;
209 *sizep += required;
210 }
211 return(kret);
212 }
213
214 /*
215 * Determine the size required for this krb5_gss_ctx_id_rec.
216 */
217 krb5_error_code
kg_ctx_size(krb5_context kcontext,krb5_gss_ctx_id_t ctx,size_t * sizep)218 kg_ctx_size(krb5_context kcontext, krb5_gss_ctx_id_t ctx, size_t *sizep)
219 {
220 krb5_error_code kret;
221 size_t required;
222
223 /*
224 * krb5_gss_ctx_id_rec requires:
225 * krb5_int32 for KG_CONTEXT
226 * krb5_int32 for initiate.
227 * krb5_int32 for established.
228 * krb5_int32 for have_acceptor_subkey.
229 * krb5_int32 for seed_init.
230 * krb5_int32 for gss_flags.
231 * sizeof(seed) for seed
232 * ... for here
233 * ... for there
234 * ... for subkey
235 * krb5_int32 for signalg.
236 * krb5_int32 for cksum_size.
237 * krb5_int32 for sealalg.
238 * ... for enc
239 * ... for seq
240 * krb5_int32 for authtime.
241 * krb5_int32 for starttime.
242 * krb5_int32 for endtime.
243 * krb5_int32 for renew_till.
244 * krb5_int32 for flags.
245 * int64_t for seq_send.
246 * int64_t for seq_recv.
247 * ... for seqstate
248 * ... for auth_context
249 * ... for mech_used
250 * krb5_int32 for proto
251 * krb5_int32 for cksumtype
252 * ... for acceptor_subkey
253 * krb5_int32 for acceptor_key_cksumtype
254 * krb5_int32 for cred_rcache
255 * krb5_int32 for number of elements in authdata array
256 * ... for authdata array
257 * krb5_int32 for trailer.
258 */
259 kret = EINVAL;
260 if (ctx != NULL) {
261 required = 21*sizeof(krb5_int32);
262 required += 2*sizeof(int64_t);
263 required += sizeof(ctx->seed);
264
265 kret = 0;
266 if (!kret && ctx->here)
267 kret = k5_size_principal(ctx->here->princ, &required);
268
269 if (!kret && ctx->there)
270 kret = k5_size_principal(ctx->there->princ, &required);
271
272 if (!kret && ctx->subkey)
273 kret = k5_size_keyblock(&ctx->subkey->keyblock, &required);
274
275 if (!kret && ctx->enc)
276 kret = k5_size_keyblock(&ctx->enc->keyblock, &required);
277
278 if (!kret && ctx->seq)
279 kret = k5_size_keyblock(&ctx->seq->keyblock, &required);
280
281 if (!kret)
282 kret = kg_oid_size(ctx->mech_used, &required);
283
284 if (!kret && ctx->seqstate)
285 kret = kg_seqstate_size(ctx->seqstate, &required);
286
287 if (!kret)
288 kret = k5_size_context(ctx->k5_context, &required);
289 if (!kret)
290 kret = k5_size_auth_context(ctx->auth_context, &required);
291 if (!kret && ctx->acceptor_subkey)
292 kret = k5_size_keyblock(&ctx->acceptor_subkey->keyblock,
293 &required);
294 if (!kret && ctx->authdata) {
295 krb5_int32 i;
296
297 for (i = 0; !kret && ctx->authdata[i]; i++)
298 kret = k5_size_authdata(ctx->authdata[i], &required);
299 }
300 if (!kret) {
301 krb5_gss_name_t initiator_name;
302
303 initiator_name = ctx->initiate ? ctx->here : ctx->there;
304
305 if (initiator_name && initiator_name->ad_context) {
306 kret = k5_size_authdata_context(kcontext,
307 initiator_name->ad_context,
308 &required);
309 }
310 }
311 *sizep += required;
312 }
313 return(kret);
314 }
315
316 /*
317 * Externalize this krb5_gss_ctx_id_ret.
318 */
319 krb5_error_code
kg_ctx_externalize(krb5_context kcontext,krb5_gss_ctx_id_t ctx,krb5_octet ** buffer,size_t * lenremain)320 kg_ctx_externalize(krb5_context kcontext, krb5_gss_ctx_id_t ctx,
321 krb5_octet **buffer, size_t *lenremain)
322 {
323 krb5_error_code kret;
324 size_t required;
325 krb5_octet *bp;
326 size_t remain;
327 krb5int_access kaccess;
328
329 kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
330 if (kret)
331 return(kret);
332
333 required = 0;
334 bp = *buffer;
335 remain = *lenremain;
336 kret = EINVAL;
337 if (ctx != NULL) {
338 kret = ENOMEM;
339 if (!kg_ctx_size(kcontext, ctx, &required) &&
340 (required <= remain)) {
341 /* Our identifier */
342 (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
343
344 /* Now static data */
345 (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate,
346 &bp, &remain);
347 (void) krb5_ser_pack_int32((krb5_int32) ctx->established,
348 &bp, &remain);
349 (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey,
350 &bp, &remain);
351 (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init,
352 &bp, &remain);
353 (void) krb5_ser_pack_int32((krb5_int32) ctx->gss_flags,
354 &bp, &remain);
355 (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed,
356 sizeof(ctx->seed),
357 &bp, &remain);
358 (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg,
359 &bp, &remain);
360 (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size,
361 &bp, &remain);
362 (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg,
363 &bp, &remain);
364 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.authtime,
365 &bp, &remain);
366 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.starttime,
367 &bp, &remain);
368 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.endtime,
369 &bp, &remain);
370 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.renew_till,
371 &bp, &remain);
372 (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags,
373 &bp, &remain);
374 (void) (*kaccess.ser_pack_int64)((int64_t) ctx->seq_send,
375 &bp, &remain);
376 (void) (*kaccess.ser_pack_int64)((int64_t) ctx->seq_recv,
377 &bp, &remain);
378
379 /* Now dynamic data */
380 kret = 0;
381
382 if (!kret && ctx->mech_used)
383 kret = kg_oid_externalize(ctx->mech_used, &bp, &remain);
384
385 if (!kret && ctx->here)
386 kret = k5_externalize_principal(ctx->here->princ,
387 &bp, &remain);
388
389 if (!kret && ctx->there)
390 kret = k5_externalize_principal(ctx->there->princ,
391 &bp, &remain);
392
393 if (!kret && ctx->subkey)
394 kret = k5_externalize_keyblock(&ctx->subkey->keyblock,
395 &bp, &remain);
396
397 if (!kret && ctx->enc)
398 kret = k5_externalize_keyblock(&ctx->enc->keyblock,
399 &bp, &remain);
400
401 if (!kret && ctx->seq)
402 kret = k5_externalize_keyblock(&ctx->seq->keyblock,
403 &bp, &remain);
404
405 if (!kret && ctx->seqstate)
406 kret = kg_seqstate_externalize(ctx->seqstate, &bp, &remain);
407
408 if (!kret)
409 kret = k5_externalize_context(ctx->k5_context, &bp, &remain);
410
411 if (!kret)
412 kret = k5_externalize_auth_context(ctx->auth_context,
413 &bp, &remain);
414
415 if (!kret)
416 kret = krb5_ser_pack_int32((krb5_int32) ctx->proto,
417 &bp, &remain);
418 if (!kret)
419 kret = krb5_ser_pack_int32((krb5_int32) ctx->cksumtype,
420 &bp, &remain);
421 if (!kret && ctx->acceptor_subkey)
422 kret = k5_externalize_keyblock(&ctx->acceptor_subkey->keyblock,
423 &bp, &remain);
424 if (!kret)
425 kret = krb5_ser_pack_int32((krb5_int32) ctx->acceptor_subkey_cksumtype,
426 &bp, &remain);
427
428 if (!kret)
429 kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache,
430 &bp, &remain);
431 if (!kret) {
432 krb5_int32 i = 0;
433
434 if (ctx->authdata) {
435 for (; ctx->authdata[i]; i++)
436 ;
437 }
438 /* authdata count */
439 kret = krb5_ser_pack_int32(i, &bp, &remain);
440 if (!kret && ctx->authdata) {
441 /* authdata */
442 for (i = 0; !kret && ctx->authdata[i]; i++)
443 kret = k5_externalize_authdata(ctx->authdata[i],
444 &bp, &remain);
445 }
446 }
447 /* authdata context */
448 if (!kret) {
449 krb5_gss_name_t initiator_name;
450
451 initiator_name = ctx->initiate ? ctx->here : ctx->there;
452
453 if (initiator_name && initiator_name->ad_context) {
454 kret = k5_externalize_authdata_context(kcontext,
455 initiator_name->
456 ad_context,
457 &bp, &remain);
458 }
459 }
460 /* trailer */
461 if (!kret)
462 kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
463 if (!kret) {
464 *buffer = bp;
465 *lenremain = remain;
466 }
467 }
468 }
469 return(kret);
470 }
471
472 /* Internalize a keyblock and convert it to a key. */
473 static krb5_error_code
intern_key(krb5_key * key,krb5_octet ** bp,size_t * sp)474 intern_key(krb5_key *key, krb5_octet **bp, size_t *sp)
475 {
476 krb5_keyblock *keyblock;
477 krb5_error_code ret;
478
479 ret = k5_internalize_keyblock(&keyblock, bp, sp);
480 if (ret != 0)
481 return ret;
482 ret = krb5_k_create_key(NULL, keyblock, key);
483 krb5_free_keyblock(NULL, keyblock);
484 return ret;
485 }
486
487 /*
488 * Internalize this krb5_gss_ctx_id_t.
489 */
490 krb5_error_code
kg_ctx_internalize(krb5_context kcontext,krb5_gss_ctx_id_t * argp,krb5_octet ** buffer,size_t * lenremain)491 kg_ctx_internalize(krb5_context kcontext, krb5_gss_ctx_id_t *argp,
492 krb5_octet **buffer, size_t *lenremain)
493 {
494 krb5_error_code kret;
495 krb5_gss_ctx_id_rec *ctx;
496 krb5_int32 ibuf;
497 krb5_octet *bp;
498 size_t remain;
499 krb5int_access kaccess;
500 krb5_principal princ;
501
502 kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
503 if (kret)
504 return(kret);
505
506 bp = *buffer;
507 remain = *lenremain;
508 kret = EINVAL;
509 princ = NULL;
510 /* Read our magic number */
511 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
512 ibuf = 0;
513 if (ibuf == KG_CONTEXT) {
514 kret = ENOMEM;
515
516 /* Get a context */
517 if ((remain >= (17*sizeof(krb5_int32)
518 + 2*sizeof(int64_t)
519 + sizeof(ctx->seed))) &&
520 (ctx = (krb5_gss_ctx_id_rec *)
521 xmalloc(sizeof(krb5_gss_ctx_id_rec)))) {
522 memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
523
524 ctx->magic = ibuf;
525
526 /* Get static data */
527 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
528 ctx->initiate = (int) ibuf;
529 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
530 ctx->established = (int) ibuf;
531 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
532 ctx->have_acceptor_subkey = (int) ibuf;
533 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
534 ctx->seed_init = (int) ibuf;
535 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
536 ctx->gss_flags = (int) ibuf;
537 (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed,
538 sizeof(ctx->seed),
539 &bp, &remain);
540 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
541 ctx->signalg = (int) ibuf;
542 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
543 ctx->cksum_size = (int) ibuf;
544 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
545 ctx->sealalg = (int) ibuf;
546 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
547 ctx->krb_times.authtime = (krb5_timestamp) ibuf;
548 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
549 ctx->krb_times.starttime = (krb5_timestamp) ibuf;
550 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
551 ctx->krb_times.endtime = (krb5_timestamp) ibuf;
552 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
553 ctx->krb_times.renew_till = (krb5_timestamp) ibuf;
554 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
555 ctx->krb_flags = (krb5_flags) ibuf;
556 (void) (*kaccess.ser_unpack_int64)((int64_t *)&ctx->seq_send,
557 &bp, &remain);
558 kret = (*kaccess.ser_unpack_int64)((int64_t *)&ctx->seq_recv,
559 &bp, &remain);
560 if (kret) {
561 free(ctx);
562 return kret;
563 }
564
565 {
566 gss_OID tmp;
567 kret = kg_oid_internalize(&tmp, &bp, &remain);
568 if (kret == 0)
569 ctx->mech_used = tmp;
570 else if (kret == EINVAL)
571 kret = 0;
572 }
573 /* Now get substructure data */
574 kret = k5_internalize_principal(&princ, &bp, &remain);
575 if (kret == 0) {
576 kret = kg_init_name(kcontext, princ, NULL, NULL, NULL,
577 KG_INIT_NAME_NO_COPY, &ctx->here);
578 if (kret)
579 krb5_free_principal(kcontext, princ);
580 } else if (kret == EINVAL)
581 kret = 0;
582 if (!kret) {
583 kret = k5_internalize_principal(&princ, &bp, &remain);
584 if (kret == 0) {
585 kret = kg_init_name(kcontext, princ, NULL, NULL, NULL,
586 KG_INIT_NAME_NO_COPY, &ctx->there);
587 if (kret)
588 krb5_free_principal(kcontext, princ);
589 } else if (kret == EINVAL)
590 kret = 0;
591 }
592 if (!kret &&
593 (kret = intern_key(&ctx->subkey, &bp, &remain))) {
594 if (kret == EINVAL)
595 kret = 0;
596 }
597 if (!kret &&
598 (kret = intern_key(&ctx->enc, &bp, &remain))) {
599 if (kret == EINVAL)
600 kret = 0;
601 }
602 if (!kret &&
603 (kret = intern_key(&ctx->seq, &bp, &remain))) {
604 if (kret == EINVAL)
605 kret = 0;
606 }
607
608 if (!kret) {
609 kret = kg_seqstate_internalize(&ctx->seqstate, &bp, &remain);
610 if (kret == EINVAL)
611 kret = 0;
612 }
613
614 if (!kret)
615 kret = k5_internalize_context(&ctx->k5_context, &bp, &remain);
616
617 if (!kret)
618 kret = k5_internalize_auth_context(&ctx->auth_context,
619 &bp, &remain);
620
621 if (!kret)
622 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
623 ctx->proto = ibuf;
624 if (!kret)
625 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
626 ctx->cksumtype = ibuf;
627 if (!kret &&
628 (kret = intern_key(&ctx->acceptor_subkey, &bp, &remain))) {
629 if (kret == EINVAL)
630 kret = 0;
631 }
632 if (!kret)
633 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
634 ctx->acceptor_subkey_cksumtype = ibuf;
635 if (!kret)
636 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
637 ctx->cred_rcache = ibuf;
638 /* authdata */
639 if (!kret)
640 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
641 if (!kret) {
642 krb5_int32 nadata = ibuf, i;
643
644 if (nadata > 0) {
645 ctx->authdata = (krb5_authdata **)calloc((size_t)nadata + 1,
646 sizeof(krb5_authdata *));
647 if (ctx->authdata == NULL) {
648 kret = ENOMEM;
649 } else {
650 for (i = 0; !kret && i < nadata; i++)
651 kret = k5_internalize_authdata(&ctx->authdata[i],
652 &bp, &remain);
653 }
654 }
655 }
656 /* authdata context */
657 if (!kret) {
658 krb5_gss_name_t initiator_name;
659
660 initiator_name = ctx->initiate ? ctx->here : ctx->there;
661 if (initiator_name == NULL) {
662 kret = EINVAL;
663 } else {
664 kret = k5_internalize_authdata_context(kcontext,
665 &initiator_name->
666 ad_context,
667 &bp, &remain);
668 if (kret == EINVAL)
669 kret = 0;
670 }
671 }
672 /* Get trailer */
673 if (!kret)
674 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
675 if (!kret && ibuf != KG_CONTEXT)
676 kret = EINVAL;
677
678 if (!kret) {
679 *buffer = bp;
680 *lenremain = remain;
681 *argp = ctx;
682 } else {
683 if (ctx->seq)
684 krb5_k_free_key(kcontext, ctx->seq);
685 if (ctx->enc)
686 krb5_k_free_key(kcontext, ctx->enc);
687 if (ctx->subkey)
688 krb5_k_free_key(kcontext, ctx->subkey);
689 if (ctx->there)
690 kg_release_name(kcontext, &ctx->there);
691 if (ctx->here)
692 kg_release_name(kcontext, &ctx->here);
693 xfree(ctx);
694 }
695 }
696 }
697 return(kret);
698 }
699