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