2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * lib/gssapi/krb5/ser_sctx.c
10 * Copyright 1995, 2004 by the Massachusetts Institute of Technology.
11 * All Rights Reserved.
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.
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.
35 * ser_sctx.c - Handle [de]serialization of GSSAPI security context.
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"
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
56 static krb5_error_code
57 kg_oid_externalize(kcontext
, arg
, buffer
, lenremain
)
58 krb5_context kcontext
;
63 gss_OID oid
= (gss_OID
) arg
;
66 err
= krb5_ser_pack_int32(KV5M_GSS_OID
, buffer
, lenremain
);
69 err
= krb5_ser_pack_int32((krb5_int32
) oid
->length
,
73 err
= krb5_ser_pack_bytes((krb5_octet
*) oid
->elements
,
74 oid
->length
, buffer
, lenremain
);
77 err
= krb5_ser_pack_int32(KV5M_GSS_OID
, buffer
, lenremain
);
82 static krb5_error_code
83 kg_oid_internalize(kcontext
, argp
, buffer
, lenremain
)
84 krb5_context kcontext
;
97 /* Read in and check our magic number */
98 if (krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
))
101 if (ibuf
!= KV5M_GSS_OID
)
104 oid
= (gss_OID
) MALLOC(sizeof(gss_OID_desc
));
107 if (krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
)) {
108 FREE(oid
, sizeof(gss_OID_desc
));
112 oid
->elements
= MALLOC(ibuf
);
113 if (oid
->elements
== 0) {
114 FREE(oid
, sizeof(gss_OID_desc
));
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
));
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
));
131 if (ibuf
!= KV5M_GSS_OID
) {
132 FREE(oid
->elements
, oid
->length
);
133 FREE(oid
, sizeof(gss_OID_desc
));
139 *argp
= (krb5_pointer
) oid
;
144 static krb5_error_code
145 kg_oid_size(kcontext
, arg
, sizep
)
146 krb5_context kcontext
;
150 krb5_error_code kret
;
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
;
170 static krb5_error_code
171 kg_queue_externalize(kcontext
, arg
, buffer
, lenremain
)
172 krb5_context kcontext
;
178 err
= krb5_ser_pack_int32(KV5M_GSS_QUEUE
, buffer
, lenremain
);
180 err
= g_queue_externalize(arg
, buffer
, lenremain
);
182 err
= krb5_ser_pack_int32(KV5M_GSS_QUEUE
, buffer
, lenremain
);
187 static krb5_error_code
188 kg_queue_internalize(kcontext
, argp
, buffer
, lenremain
)
189 krb5_context kcontext
;
202 /* Read in and check our magic number */
203 if (krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
))
206 if (ibuf
!= KV5M_GSS_QUEUE
)
209 err
= g_queue_internalize(argp
, &bp
, &remain
);
213 /* Read in and check our trailing magic number */
214 if (krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
)) {
219 if (ibuf
!= KV5M_GSS_QUEUE
) {
230 static krb5_error_code
231 kg_queue_size(kcontext
, arg
, sizep
)
232 krb5_context kcontext
;
236 krb5_error_code kret
;
241 required
= 2*sizeof(krb5_int32
); /* For the header and trailer */
242 (void) g_queue_size(arg
, &required
);
251 * Determine the size required for this krb5_gss_ctx_id_rec.
254 kg_ctx_size(kcontext
, arg
, sizep
)
255 krb5_context kcontext
;
259 krb5_error_code kret
;
260 krb5_gss_ctx_id_rec
*ctx
;
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
276 * krb5_int32 for signalg.
277 * krb5_int32 for cksum_size.
278 * krb5_int32 for sealalg.
281 * krb5_int32 for endtime.
282 * krb5_int32 for flags.
283 * krb5_int64 for seq_send.
284 * krb5_int64 for seq_recv.
286 * ... for auth_context
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.
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
);
303 if (!kret
&& ctx
->here
)
304 kret
= krb5_size_opaque(kcontext
,
306 (krb5_pointer
) ctx
->here
,
309 if (!kret
&& ctx
->there
)
310 kret
= krb5_size_opaque(kcontext
,
312 (krb5_pointer
) ctx
->there
,
315 if (!kret
&& ctx
->subkey
)
316 kret
= krb5_size_opaque(kcontext
,
318 (krb5_pointer
) ctx
->subkey
,
321 if (!kret
&& ctx
->enc
)
322 kret
= krb5_size_opaque(kcontext
,
324 (krb5_pointer
) ctx
->enc
,
327 if (!kret
&& ctx
->seq
)
328 kret
= krb5_size_opaque(kcontext
,
330 (krb5_pointer
) ctx
->seq
,
334 kret
= kg_oid_size(kcontext
,
335 (krb5_pointer
) ctx
->mech_used
,
338 if (!kret
&& ctx
->seqstate
)
339 kret
= kg_queue_size(kcontext
, ctx
->seqstate
, &required
);
341 #ifndef PROVIDE_KERNEL_IMPORT
343 kret
= krb5_size_opaque(kcontext
,
345 (krb5_pointer
) ctx
->k5_context
,
348 kret
= krb5_size_opaque(kcontext
,
350 (krb5_pointer
) ctx
->auth_context
,
354 if (!kret
&& ctx
->acceptor_subkey
)
355 kret
= krb5_size_opaque(kcontext
,
357 (krb5_pointer
) ctx
->acceptor_subkey
,
366 * Externalize this krb5_gss_ctx_id_ret.
369 kg_ctx_externalize(kcontext
, arg
, buffer
, lenremain
)
370 krb5_context kcontext
;
375 krb5_error_code kret
;
376 krb5_gss_ctx_id_rec
*ctx
;
381 krb5int_access kaccess
;
383 kret
= krb5int_accessor (&kaccess
, KRB5INT_ACCESS_VERSION
);
393 if ((ctx
= (krb5_gss_ctx_id_rec
*) arg
)) {
395 if (!kg_ctx_size(kcontext
, arg
, &required
) &&
396 (required
<= remain
)) {
398 (void) krb5_ser_pack_int32(KG_CONTEXT
, &bp
, &remain
);
400 /* Now static data */
401 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->initiate
,
403 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->established
,
405 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->big_endian
,
407 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->have_acceptor_subkey
,
409 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->seed_init
,
411 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->gss_flags
,
413 (void) krb5_ser_pack_bytes((krb5_octet
*) ctx
->seed
,
416 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->signalg
,
418 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->cksum_size
,
420 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->sealalg
,
422 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->endtime
,
424 (void) krb5_ser_pack_int32((krb5_int32
) ctx
->krb_flags
,
427 (void) (*kaccess
.krb5_ser_pack_int64
)((krb5_int64
) ctx
->seq_send
,
429 (void) (*kaccess
.krb5_ser_pack_int64
)((krb5_int64
) ctx
->seq_recv
,
432 (void) krb5_ser_pack_int64((krb5_int64
) ctx
->seq_send
,
434 (void) krb5_ser_pack_int64((krb5_int64
) ctx
->seq_recv
,
438 /* Now dynamic data */
441 if (!kret
&& ctx
->mech_used
)
442 kret
= kg_oid_externalize(kcontext
, ctx
->mech_used
,
445 if (!kret
&& ctx
->here
)
446 kret
= krb5_externalize_opaque(kcontext
,
448 (krb5_pointer
) ctx
->here
,
451 if (!kret
&& ctx
->there
)
452 kret
= krb5_externalize_opaque(kcontext
,
454 (krb5_pointer
) ctx
->there
,
457 if (!kret
&& ctx
->subkey
)
458 kret
= krb5_externalize_opaque(kcontext
,
460 (krb5_pointer
) ctx
->subkey
,
463 if (!kret
&& ctx
->enc
)
464 kret
= krb5_externalize_opaque(kcontext
,
466 (krb5_pointer
) ctx
->enc
,
469 if (!kret
&& ctx
->seq
)
470 kret
= krb5_externalize_opaque(kcontext
,
472 (krb5_pointer
) ctx
->seq
,
475 if (!kret
&& ctx
->seqstate
)
476 kret
= kg_queue_externalize(kcontext
,
477 ctx
->seqstate
, &bp
, &remain
);
479 #ifndef PROVIDE_KERNEL_IMPORT
481 kret
= krb5_externalize_opaque(kcontext
,
483 (krb5_pointer
) ctx
->k5_context
,
486 kret
= krb5_externalize_opaque(kcontext
,
488 (krb5_pointer
) ctx
->auth_context
,
492 kret
= krb5_ser_pack_int32((krb5_int32
) ctx
->proto
,
495 kret
= krb5_ser_pack_int32((krb5_int32
) ctx
->cksumtype
,
497 if (!kret
&& ctx
->acceptor_subkey
)
498 kret
= krb5_externalize_opaque(kcontext
,
500 (krb5_pointer
) ctx
->acceptor_subkey
,
503 kret
= krb5_ser_pack_int32((krb5_int32
) ctx
->acceptor_subkey_cksumtype
,
507 kret
= krb5_ser_pack_int32((krb5_int32
) ctx
->cred_rcache
,
511 kret
= krb5_ser_pack_int32(KG_CONTEXT
, &bp
, &remain
);
522 * Internalize this krb5_gss_ctx_id_t.
525 kg_ctx_internalize(kcontext
, argp
, buffer
, lenremain
)
526 krb5_context kcontext
;
531 krb5_error_code kret
;
532 krb5_gss_ctx_id_rec
*ctx
;
537 krb5int_access kaccess
;
539 kret
= krb5int_accessor (&kaccess
, KRB5INT_ACCESS_VERSION
);
547 /* Read our magic number */
548 if (krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
))
550 if (ibuf
== KG_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
));
561 ctx
->k5_context
= kcontext
;
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
,
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
;
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
);
593 (void) krb5_ser_unpack_int64((krb5_int64
*) (&ctx
->seq_send
),
595 kret
= krb5_ser_unpack_int64((krb5_int64
*) (&ctx
->seq_recv
),
599 xfree_wrap(ctx
, sizeof (krb5_gss_ctx_id_rec
));
603 if ((kret
= kg_oid_internalize(kcontext
,
604 (krb5_pointer
*) &ctx
->mech_used
, &bp
,
609 /* Now get substructure data */
610 if ((kret
= krb5_internalize_opaque(kcontext
,
612 (krb5_pointer
*) &ctx
->here
,
618 (kret
= krb5_internalize_opaque(kcontext
,
620 (krb5_pointer
*) &ctx
->there
,
626 (kret
= krb5_internalize_opaque(kcontext
,
628 (krb5_pointer
*) &ctx
->subkey
,
634 (kret
= krb5_internalize_opaque(kcontext
,
636 (krb5_pointer
*) &ctx
->enc
,
642 (kret
= krb5_internalize_opaque(kcontext
,
644 (krb5_pointer
*) &ctx
->seq
,
651 kret
= kg_queue_internalize(kcontext
, &ctx
->seqstate
,
657 #ifndef PROVIDE_KERNEL_IMPORT
659 kret
= krb5_internalize_opaque(kcontext
,
661 (krb5_pointer
*) &ctx
->k5_context
,
665 kret
= krb5_internalize_opaque(kcontext
,
667 (krb5_pointer
*) &ctx
->auth_context
,
671 kret
= krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
);
674 kret
= krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
);
675 ctx
->cksumtype
= ibuf
;
677 (kret
= krb5_internalize_opaque(kcontext
,
679 (krb5_pointer
*) &ctx
->acceptor_subkey
,
685 kret
= krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
);
686 ctx
->cred_rcache
= ibuf
;
688 kret
= krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
);
689 ctx
->acceptor_subkey_cksumtype
= ibuf
;
693 kret
= krb5_ser_unpack_int32(&ibuf
, &bp
, &remain
);
694 if (!kret
&& ibuf
!= KG_CONTEXT
)
700 *argp
= (krb5_pointer
) ctx
;
703 krb5_free_keyblock(kcontext
, ctx
->seq
);
705 krb5_free_keyblock(kcontext
, ctx
->enc
);
707 krb5_free_keyblock(kcontext
, ctx
->subkey
);
709 krb5_free_principal(kcontext
, ctx
->there
);
711 krb5_free_principal(kcontext
, ctx
->here
);
712 xfree_wrap(ctx
, sizeof (krb5_gss_ctx_id_rec
));