From: Paul Park Date: Tue, 29 Aug 1995 18:42:09 +0000 (+0000) Subject: Add new modules to support {im,ex}port of GSSAPI context X-Git-Tag: krb5-1.0-beta6~1231 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ee279c1e195f5e6ff1cf3be37432f5d62834f91c;p=krb5.git Add new modules to support {im,ex}port of GSSAPI context git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6625 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/gssapi/krb5/.Sanitize b/src/lib/gssapi/krb5/.Sanitize index f23990b53..9fe1b32f8 100644 --- a/src/lib/gssapi/krb5/.Sanitize +++ b/src/lib/gssapi/krb5/.Sanitize @@ -36,12 +36,14 @@ context_time.c delete_sec_context.c disp_name.c disp_status.c +export_sec_context.c get_tkt_flags.c gssapiP_krb5.h gssapi_err_krb5.et gssapi_krb5.c gssapi_krb5.h import_name.c +import_sec_context.c indicate_mechs.c init_sec_context.c inq_context.c @@ -53,6 +55,7 @@ process_context_token.c rel_cred.c rel_name.c seal.c +ser_sctx.c sign.c unseal.c util_cksum.c diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in index 0f52e7c19..0c9fbe167 100644 --- a/src/lib/gssapi/krb5/Makefile.in +++ b/src/lib/gssapi/krb5/Makefile.in @@ -25,9 +25,11 @@ CCSRCS = \ $(srcdir)/delete_sec_context.c \ $(srcdir)/disp_name.c \ $(srcdir)/disp_status.c \ + $(srcdir)/export_sec_context.c \ $(srcdir)/get_tkt_flags.c \ $(srcdir)/gssapi_krb5.c \ $(srcdir)/import_name.c \ + $(srcdir)/import_sec_context.c \ $(srcdir)/indicate_mechs.c \ $(srcdir)/init_sec_context.c \ $(srcdir)/inq_context.c \ @@ -39,6 +41,7 @@ CCSRCS = \ $(srcdir)/rel_cred.c \ $(srcdir)/rel_name.c \ $(srcdir)/seal.c \ + $(srcdir)/ser_sctx.c \ $(srcdir)/sign.c \ $(srcdir)/unseal.c \ $(srcdir)/util_cksum.c \ @@ -55,9 +58,11 @@ CCOBJS = \ delete_sec_context.$(OBJEXT) \ disp_name.$(OBJEXT) \ disp_status.$(OBJEXT) \ + export_sec_context.$(OBJEXT) \ get_tkt_flags.$(OBJEXT) \ gssapi_krb5.$(OBJEXT) \ import_name.$(OBJEXT) \ + import_sec_context.$(OBJEXT) \ indicate_mechs.$(OBJEXT) \ init_sec_context.$(OBJEXT) \ inq_context.$(OBJEXT) \ @@ -69,6 +74,7 @@ CCOBJS = \ rel_cred.$(OBJEXT) \ rel_name.$(OBJEXT) \ seal.$(OBJEXT) \ + ser_sctx.$(OBJEXT) \ sign.$(OBJEXT) \ unseal.$(OBJEXT) \ util_cksum.$(OBJEXT) \ diff --git a/src/lib/gssapi/krb5/export_sec_context.c b/src/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 000000000..4f07bcb5a --- /dev/null +++ b/src/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,122 @@ +/* + * lib/gssapi/krb5/export_sec_context.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * export_sec_context.c - Externalize the security context. + */ +#include "gssapiP_krb5.h" + +OM_uint32 +krb5_gss_export_sec_context(context, + minor_status, context_handle, interprocess_token) + krb5_context context; + OM_uint32 *minor_status; + gss_ctx_id_t *context_handle; + gss_buffer_t interprocess_token; +{ + krb5_error_code kret; + OM_uint32 retval; + krb5_context ser_ctx; + size_t bufsize, blen; + krb5_gss_ctx_id_t *ctx; + krb5_octet *obuffer, *obp; + + /* Assume a tragic failure */ + ser_ctx = (krb5_context) NULL; + obuffer = (krb5_octet *) NULL; + retval = GSS_S_FAILURE; + *minor_status = 0; + + /* Get a fresh Kerberos context */ + if (!(kret = krb5_init_context(&ser_ctx))) { + /* Initialize the serializers */ + if (!(kret = krb5_ser_context_init(ser_ctx)) && + !(kret = krb5_ser_auth_context_init(ser_ctx)) && + !(kret = krb5_ser_ccache_init(ser_ctx)) && + !(kret = krb5_ser_rcache_init(ser_ctx)) && + !(kret = krb5_ser_keytab_init(ser_ctx)) && + !(kret = kg_ser_context_init(ser_ctx))) { + if (kg_validate_ctx_id(*context_handle)) { + ctx = (krb5_gss_ctx_id_t *) *context_handle; + + /* Determine size needed for externalization of context */ + bufsize = 0; + if (!(kret = krb5_size_opaque(ser_ctx, + KG_CONTEXT, + (krb5_pointer) ctx, + &bufsize))) { + /* Allocate the buffer */ + if ((obuffer = (krb5_octet *) xmalloc(bufsize))) { + obp = obuffer; + blen = bufsize; + /* Externalize the context */ + if (!(kret = krb5_externalize_opaque(ser_ctx, + KG_CONTEXT, + (krb5_pointer)ctx, + &obp, + &blen))) { + /* Success! Return the buffer */ + interprocess_token->length = bufsize - blen; + interprocess_token->value = obuffer; + *minor_status = 0; + retval = GSS_S_COMPLETE; + + /* Now, clean up the context state */ + (void) kg_delete_ctx_id((gss_ctx_id_t) ctx); + if (ctx->enc.processed) + krb5_finish_key(ctx->context, + &ctx->enc.eblock); + krb5_free_keyblock(ctx->context, ctx->enc.key); + if (ctx->seq.processed) + krb5_finish_key(ctx->context, + &ctx->seq.eblock); + krb5_free_principal(ctx->context, ctx->here); + krb5_free_principal(ctx->context, ctx->there); + krb5_free_keyblock(ctx->context, ctx->subkey); + + /* Zero out context */ + memset(ctx, 0, sizeof(*ctx)); + xfree(ctx); + *context_handle = GSS_C_NO_CONTEXT; + } + } + } + } + else { + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + retval = GSS_S_NO_CONTEXT; + } + } + krb5_free_context(ser_ctx); + } + if (retval != GSS_S_COMPLETE) { + if (obuffer && bufsize) { + memset(obuffer, 0, bufsize); + krb5_xfree(obuffer); + } + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + } + return(retval); +} diff --git a/src/lib/gssapi/krb5/import_sec_context.c b/src/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 000000000..1c9ffabd8 --- /dev/null +++ b/src/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,101 @@ +/* + * lib/gssapi/krb5/import_sec_context.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * import_sec_context.c - Internalize the security context. + */ +#include "gssapiP_krb5.h" + +OM_uint32 +krb5_gss_import_sec_context(context, + minor_status, interprocess_token, context_handle) + krb5_context context; + OM_uint32 *minor_status; + gss_buffer_t interprocess_token; + gss_ctx_id_t *context_handle; +{ + krb5_error_code kret; + OM_uint32 retval; + krb5_context ser_ctx; + size_t blen; + krb5_gss_ctx_id_t *ctx; + krb5_octet *ibp; + + /* Assume a tragic failure */ + ser_ctx = (krb5_context) NULL; + ctx = (krb5_gss_ctx_id_t *) NULL; + retval = GSS_S_FAILURE; + *minor_status = 0; + + /* Get a fresh Kerberos context */ + if (!(kret = krb5_init_context(&ser_ctx))) { + /* Initialize the serializers */ + if (!(kret = krb5_ser_context_init(ser_ctx)) && + !(kret = krb5_ser_auth_context_init(ser_ctx)) && + !(kret = krb5_ser_ccache_init(ser_ctx)) && + !(kret = krb5_ser_rcache_init(ser_ctx)) && + !(kret = krb5_ser_keytab_init(ser_ctx)) && + !(kret = kg_ser_context_init(ser_ctx))) { + + /* Internalize the context */ + ibp = (krb5_octet *) interprocess_token->value; + blen = (size_t) interprocess_token->length; + if (!(kret = krb5_internalize_opaque(ser_ctx, + KG_CONTEXT, + (krb5_pointer *) &ctx, + &ibp, + &blen))) { + + /* Make sure that everything is cool. */ + if (kg_validate_ctx_id((gss_ctx_id_t) ctx)) { + interprocess_token->value = ibp; + interprocess_token->length = blen; + *context_handle = (gss_ctx_id_t) ctx; + retval = GSS_S_COMPLETE; + } + } + } + krb5_free_context(ser_ctx); + } + if (retval != GSS_S_COMPLETE) { + if (ctx) { + (void) kg_delete_ctx_id((gss_ctx_id_t) ctx); + if (ctx->enc.processed) + krb5_finish_key(ctx->context, &ctx->enc.eblock); + krb5_free_keyblock(ctx->context, ctx->enc.key); + if (ctx->seq.processed) + krb5_finish_key(ctx->context, &ctx->seq.eblock); + krb5_free_principal(ctx->context, ctx->here); + krb5_free_principal(ctx->context, ctx->there); + krb5_free_keyblock(ctx->context, ctx->subkey); + + /* Zero out context */ + memset(ctx, 0, sizeof(*ctx)); + xfree(ctx); + } + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + } + return(retval); +} diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c new file mode 100644 index 000000000..c1ddfd701 --- /dev/null +++ b/src/lib/gssapi/krb5/ser_sctx.c @@ -0,0 +1,828 @@ +/* + * lib/gssapi/krb5/ser_sctx.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * ser_sctx.c - Handle [de]serialization of GSSAPI security context. + */ +#include "gssapiP_krb5.h" + +/* + * This module contains routines to [de]serialize krb5_gss_cred_id_t, + * krb5_gss_enc_desc and krb5_gss_ctx_id_t. + */ + +/* + * Determine the size required for this krb5_gss_cred_id_t. + */ +static krb5_error_code +kg_cred_size(kcontext, arg, sizep) + krb5_context kcontext; + krb5_pointer arg; + size_t *sizep; +{ + krb5_error_code kret; + krb5_gss_cred_id_t cred; + size_t required; + + /* + * krb5_gss_cred_id_t requires: + * krb5_int32 for KG_CRED + * krb5_int32 for usage. + * krb5_int32 for tgt_expire. + * krb5_int32 for trailer. + */ + kret = EINVAL; + if ((cred = (krb5_gss_cred_id_t) arg)) { + required = 4*sizeof(krb5_int32); + kret = 0; + if (cred->princ) + kret = krb5_size_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer) cred->princ, + &required); + if (!kret && cred->keytab) + kret = krb5_size_opaque(kcontext, + KV5M_KEYTAB, + (krb5_pointer) cred->keytab, + &required); + + if (!kret && cred->ccache) + kret = krb5_size_opaque(kcontext, + KV5M_CCACHE, + (krb5_pointer) cred->ccache, + &required); + if (!kret) + *sizep += required; + } + return(kret); +} + +/* + * Externalize this krb5_gss_cred_id_t. + */ +static krb5_error_code +kg_cred_externalize(kcontext, arg, buffer, lenremain) + krb5_context kcontext; + krb5_pointer arg; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code kret; + krb5_gss_cred_id_t cred; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if ((cred = (krb5_gss_cred_id_t) arg)) { + kret = ENOMEM; + if (!kg_cred_size(kcontext, arg, &required) && + (required <= remain)) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KG_CRED, &bp, &remain); + + /* Now static data */ + (void) krb5_ser_pack_int32((krb5_int32) cred->usage, &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) cred->tgt_expire, + &bp, &remain); + + /* Now pack up dynamic data */ + if (cred->princ) + kret = krb5_externalize_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer) cred->princ, + &bp, &remain); + else + kret = 0; + + if (!kret && cred->keytab) + kret = krb5_externalize_opaque(kcontext, + KV5M_KEYTAB, + (krb5_pointer) cred->keytab, + &bp, &remain); + + if (!kret && cred->ccache) + kret = krb5_externalize_opaque(kcontext, + KV5M_CCACHE, + (krb5_pointer) cred->ccache, + &bp, &remain); + + if (!kret) { + (void) krb5_ser_pack_int32(KG_CRED, &bp, &remain); + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +/* + * Internalize this krb5_gss_cred_id_t. + */ +static krb5_error_code +kg_cred_internalize(kcontext, argp, buffer, lenremain) + krb5_context kcontext; + krb5_pointer *argp; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code kret; + krb5_gss_cred_id_t cred; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KG_CRED) { + kret = ENOMEM; + + /* Get a cred */ + if ((remain >= (2*sizeof(krb5_int32))) && + (cred = (krb5_gss_cred_id_t) + xmalloc(sizeof(krb5_gss_cred_id_rec)))) { + memset(cred, 0, sizeof(krb5_gss_cred_id_rec)); + + /* Get the static data */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + cred->usage = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + cred->tgt_expire = (krb5_timestamp) ibuf; + + /* cred->princ */ + if ((kret = krb5_internalize_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer *) &cred->princ, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + + /* cred->keytab */ + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_KEYTAB, + (krb5_pointer *) &cred->keytab, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + + /* cred->ccache */ + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_CCACHE, + (krb5_pointer *) &cred->ccache, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + + /* trailer */ + if (!kret && + !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) && + (ibuf == KG_CRED)) { + *buffer = bp; + *lenremain = remain; + *argp = (krb5_pointer) cred; + } + else { + if (!kret && (ibuf != KG_CRED)) + kret = EINVAL; + if (cred->ccache) + krb5_cc_close(kcontext, cred->ccache); + if (cred->keytab) + krb5_kt_close(kcontext, cred->keytab); + if (cred->princ) + krb5_free_principal(kcontext, cred->princ); + xfree(cred); + } + } + } + return(kret); +} + +/* + * Determine the size required for this krb5_gss_enc_desc. + */ +static krb5_error_code +kg_enc_desc_size(kcontext, arg, sizep) + krb5_context kcontext; + krb5_pointer arg; + size_t *sizep; +{ + krb5_error_code kret; + krb5_gss_enc_desc *edescp; + size_t required; + + /* + * krb5_gss_cred_id_t requires: + * krb5_int32 for KG_ENC_DESC + * krb5_int32 for processed. + * krb5_int32 for trailer. + */ + kret = EINVAL; + if ((edescp = (krb5_gss_enc_desc *) arg)) { + required = 3*sizeof(krb5_int32); + if (edescp->key) + kret = krb5_size_opaque(kcontext, + KV5M_KEYBLOCK, + (krb5_pointer) edescp->key, + &required); + else + kret = 0; + + /* + * We need to use size_opaque here because we're not sure as to the + * ancestry of this eblock, and we can't be sure that the magic number + * is set in it, so we ASSuME that it's ok. + */ + if (!kret) + kret = krb5_size_opaque(kcontext, + KV5M_ENCRYPT_BLOCK, + (krb5_pointer) &edescp->eblock, + &required); + + if (!kret) + *sizep += required; + } + return(kret); +} + +/* + * Externalize this krb5_gss_enc_desc. + */ +static krb5_error_code +kg_enc_desc_externalize(kcontext, arg, buffer, lenremain) + krb5_context kcontext; + krb5_pointer arg; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code kret; + krb5_gss_enc_desc *enc_desc; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if ((enc_desc = (krb5_gss_enc_desc *) arg)) { + kret = ENOMEM; + if (!kg_enc_desc_size(kcontext, arg, &required) && + (required <= remain)) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KG_ENC_DESC, &bp, &remain); + + /* Now static data */ + (void) krb5_ser_pack_int32((krb5_int32) enc_desc->processed, + &bp, &remain); + + /* Now pack up dynamic data */ + if (enc_desc->key) + kret = krb5_externalize_opaque(kcontext, + KV5M_KEYBLOCK, + (krb5_pointer) enc_desc->key, + &bp, &remain); + else + kret = 0; + + if (!kret) + kret = krb5_externalize_opaque(kcontext, + KV5M_ENCRYPT_BLOCK, + (krb5_pointer)&enc_desc->eblock, + &bp, &remain); + if (!kret) { + (void) krb5_ser_pack_int32(KG_ENC_DESC, &bp, &remain); + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +/* + * Internalize this krb5_gss_enc_desc. + */ +static krb5_error_code +kg_enc_desc_internalize(kcontext, argp, buffer, lenremain) + krb5_context kcontext; + krb5_pointer *argp; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code kret; + krb5_gss_enc_desc *edescp; + krb5_int32 ibuf; + krb5_octet *bp; + krb5_encrypt_block *eblockp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KG_ENC_DESC) { + kret = ENOMEM; + + /* Get an enc_desc */ + if ((remain >= (2*sizeof(krb5_int32))) && + (edescp = (krb5_gss_enc_desc *) + xmalloc(sizeof(krb5_gss_enc_desc)))) { + memset(edescp, 0, sizeof(krb5_gss_enc_desc)); + + /* Get the static data */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + edescp->processed = (int) ibuf; + + /* edescp->key */ + if ((kret = krb5_internalize_opaque(kcontext, + KV5M_KEYBLOCK, + (krb5_pointer *) &edescp->key, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + + /* edescp->eblock */ + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_ENCRYPT_BLOCK, + (krb5_pointer *) &eblockp, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + else { + /* Successful, copy in allocated eblock to our structure */ + memcpy(&edescp->eblock, eblockp, sizeof(edescp->eblock)); + krb5_xfree(eblockp); + } + + /* trailer */ + if (!kret && + !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) && + (ibuf == KG_ENC_DESC)) { + *buffer = bp; + *lenremain = remain; + *argp = (krb5_pointer) edescp; + } + else { + if (!kret && (ibuf != KG_ENC_DESC)) + kret = EINVAL; + if (edescp->eblock.key) + krb5_free_keyblock(kcontext, edescp->eblock.key); + if (edescp->eblock.priv && edescp->eblock.priv_size) + krb5_xfree(edescp->eblock.priv); + if (edescp->key) + krb5_free_keyblock(kcontext, edescp->key); + xfree(edescp); + } + } + } + return(kret); +} + +/* + * Determine the size required for this krb5_gss_ctx_id_t. + */ +static krb5_error_code +kg_ctx_size(kcontext, arg, sizep) + krb5_context kcontext; + krb5_pointer arg; + size_t *sizep; +{ + krb5_error_code kret; + krb5_gss_ctx_id_t *ctx; + size_t required; + + /* + * krb5_gss_ctx_id_t requires: + * krb5_int32 for KG_CONTEXT + * krb5_int32 for initiate. + * krb5_int32 for mutual. + * krb5_int32 for seed_init. + * sizeof(seed) for seed + * krb5_int32 for endtime. + * krb5_int32 for flags. + * krb5_int32 for seq_send. + * krb5_int32 for seq_recv. + * krb5_int32 for established. + * krb5_int32 for big_endian. + * krb5_int32 for trailer. + */ + kret = EINVAL; + if ((ctx = (krb5_gss_ctx_id_t *) arg)) { + required = 11*sizeof(krb5_int32); + required += sizeof(ctx->seed); + + kret = 0; + if (ctx->cred) + kret = krb5_size_opaque(kcontext, + KG_CRED, + (krb5_pointer) ctx->cred, + &required); + + if (!kret && ctx->here) + kret = krb5_size_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer) ctx->here, + &required); + + if (!kret && ctx->there) + kret = krb5_size_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer) ctx->there, + &required); + + if (!kret && ctx->subkey) + kret = krb5_size_opaque(kcontext, + KV5M_KEYBLOCK, + (krb5_pointer) ctx->subkey, + &required); + + if (!kret) + kret = krb5_size_opaque(kcontext, + KG_ENC_DESC, + (krb5_pointer) &ctx->enc, + &required); + + if (!kret) + kret = krb5_size_opaque(kcontext, + KG_ENC_DESC, + (krb5_pointer) &ctx->seq, + &required); + + if (!kret && ctx->context) + kret = krb5_size_opaque(kcontext, + KV5M_CONTEXT, + (krb5_pointer) ctx->context, + &required); + + if (!kret && ctx->auth_context) + kret = krb5_size_opaque(kcontext, + KV5M_AUTH_CONTEXT, + (krb5_pointer) ctx->auth_context, + &required); + + if (!kret) + *sizep += required; + } + return(kret); +} + +/* + * Externalize this krb5_gss_ctx_id_t. + */ +static krb5_error_code +kg_ctx_externalize(kcontext, arg, buffer, lenremain) + krb5_context kcontext; + krb5_pointer arg; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code kret; + krb5_gss_ctx_id_t *ctx; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if ((ctx = (krb5_gss_ctx_id_t *) arg)) { + kret = ENOMEM; + if (!kg_ctx_size(kcontext, arg, &required) && + (required <= remain)) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); + + /* Now static data */ + (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->mutual, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init, + &bp, &remain); + (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed, + sizeof(ctx->seed), + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->endtime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->flags, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->seq_send, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->seq_recv, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->established, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian, + &bp, &remain); + + /* Now dynamic data */ + if (ctx->cred) + kret = krb5_externalize_opaque(kcontext, + KG_CRED, + (krb5_pointer) ctx->cred, + &bp, &remain); + else + kret = 0; + + if (!kret && ctx->here) + kret = krb5_externalize_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer) ctx->here, + &bp, &remain); + + if (!kret && ctx->there) + kret = krb5_externalize_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer) ctx->there, + &bp, &remain); + + if (!kret && ctx->subkey) + kret = krb5_externalize_opaque(kcontext, + KV5M_KEYBLOCK, + (krb5_pointer) ctx->subkey, + &bp, &remain); + + if (!kret) + kret = krb5_externalize_opaque(kcontext, + KG_ENC_DESC, + (krb5_pointer) &ctx->enc, + &bp, &remain); + + if (!kret) + kret = krb5_externalize_opaque(kcontext, + KG_ENC_DESC, + (krb5_pointer) &ctx->seq, + &bp, &remain); + + if (!kret && ctx->context) + kret = krb5_externalize_opaque(kcontext, + KV5M_CONTEXT, + (krb5_pointer) ctx->context, + &bp, &remain); + + if (!kret && ctx->auth_context) + kret = krb5_externalize_opaque(kcontext, + KV5M_AUTH_CONTEXT, + (krb5_pointer)ctx->auth_context, + &bp, &remain); + + if (!kret) { + (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +/* + * Internalize this krb5_gss_ctx_id_t. + */ +static krb5_error_code +kg_ctx_internalize(kcontext, argp, buffer, lenremain) + krb5_context kcontext; + krb5_pointer *argp; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code kret; + krb5_gss_ctx_id_t *ctx; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + krb5_gss_enc_desc *edp; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KG_CONTEXT) { + kret = ENOMEM; + + /* Get a context */ + if ((remain >= ((10*sizeof(krb5_int32))+sizeof(ctx->seed))) && + (ctx = (krb5_gss_ctx_id_t *) + xmalloc(sizeof(krb5_gss_ctx_id_t)))) { + memset(ctx, 0, sizeof(krb5_gss_ctx_id_t)); + + /* Get static data */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->initiate = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->mutual = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->seed_init = (int) ibuf; + (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed, + sizeof(ctx->seed), + &bp, &remain); + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->endtime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->flags = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ctx->seq_send, &bp, &remain); + (void) krb5_ser_unpack_int32(&ctx->seq_recv, &bp, &remain); + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->established = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->big_endian = (int) ibuf; + + /* Now get substructure data */ + if ((kret = krb5_internalize_opaque(kcontext, + KG_CRED, + (krb5_pointer *) &ctx->cred, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer *) &ctx->here, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_PRINCIPAL, + (krb5_pointer *) &ctx->there, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_KEYBLOCK, + (krb5_pointer *) &ctx->subkey, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret) { + if ((kret = krb5_internalize_opaque(kcontext, + KG_ENC_DESC, + (krb5_pointer *) &edp, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + else { + memcpy(&ctx->enc, edp, sizeof(ctx->enc)); + xfree(edp); + } + } + if (!kret) { + if ((kret = krb5_internalize_opaque(kcontext, + KG_ENC_DESC, + (krb5_pointer *) &edp, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + else { + memcpy(&ctx->seq, edp, sizeof(ctx->seq)); + xfree(edp); + } + } + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_CONTEXT, + (krb5_pointer *) &ctx->context, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = krb5_internalize_opaque(kcontext, + KV5M_AUTH_CONTEXT, + (krb5_pointer *) + &ctx->auth_context, + &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + + /* Get trailer */ + if (!kret && + !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) && + (ibuf == KG_CONTEXT)) { + *buffer = bp; + *lenremain = remain; + *argp = (krb5_pointer) ctx; + } + else { + if (!kret && (ibuf != KG_CONTEXT)) + kret = EINVAL; + if (ctx->auth_context) + krb5_auth_con_free(kcontext, ctx->auth_context); + if (ctx->context) + krb5_free_context(ctx->context); + if (ctx->seq.eblock.key) + krb5_free_keyblock(kcontext, ctx->seq.eblock.key); + if (ctx->seq.eblock.priv && ctx->seq.eblock.priv_size) + krb5_xfree(ctx->seq.eblock.priv); + if (ctx->seq.key) + krb5_free_keyblock(kcontext, ctx->seq.key); + if (ctx->enc.eblock.key) + krb5_free_keyblock(kcontext, ctx->enc.eblock.key); + if (ctx->enc.eblock.priv && ctx->enc.eblock.priv_size) + krb5_xfree(ctx->enc.eblock.priv); + if (ctx->enc.key) + krb5_free_keyblock(kcontext, ctx->enc.key); + if (ctx->subkey) + krb5_free_keyblock(kcontext, ctx->subkey); + if (ctx->there) + krb5_free_principal(kcontext, ctx->there); + if (ctx->here) + krb5_free_principal(kcontext, ctx->here); + if (ctx->cred) { + if (ctx->cred->ccache) + krb5_cc_close(kcontext, ctx->cred->ccache); + if (ctx->cred->keytab) + krb5_kt_close(kcontext, ctx->cred->keytab); + if (ctx->cred->princ) + krb5_free_principal(kcontext, ctx->cred->princ); + krb5_xfree(ctx->cred); + } + xfree(ctx); + } + } + } + return(kret); +} + +static const krb5_ser_entry kg_cred_ser_entry = { + KG_CRED, /* Type */ + kg_cred_size, /* Sizer routine */ + kg_cred_externalize, /* Externalize routine */ + kg_cred_internalize /* Internalize routine */ +}; +static const krb5_ser_entry kg_enc_desc_ser_entry = { + KG_ENC_DESC, /* Type */ + kg_enc_desc_size, /* Sizer routine */ + kg_enc_desc_externalize, /* Externalize routine */ + kg_enc_desc_internalize /* Internalize routine */ +}; +static const krb5_ser_entry kg_ctx_ser_entry = { + KG_CONTEXT, /* Type */ + kg_ctx_size, /* Sizer routine */ + kg_ctx_externalize, /* Externalize routine */ + kg_ctx_internalize /* Internalize routine */ +}; + +krb5_error_code +kg_ser_context_init(kcontext) + krb5_context kcontext; +{ + krb5_error_code kret; + + kret = krb5_register_serializer(kcontext, &kg_cred_ser_entry); + if (!kret) + kret = krb5_register_serializer(kcontext, &kg_enc_desc_ser_entry); + if (!kret) + kret = krb5_register_serializer(kcontext, &kg_ctx_ser_entry); + return(kret); +}