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