1*ab9b2e15Sgtb #pragma ident "%Z%%M% %I% %E% SMI" 2*ab9b2e15Sgtb 3*ab9b2e15Sgtb /* 4*ab9b2e15Sgtb * lib/gssapi/krb5/lucid_context.c 5*ab9b2e15Sgtb * 6*ab9b2e15Sgtb * Copyright 2004 by the Massachusetts Institute of Technology. 7*ab9b2e15Sgtb * All Rights Reserved. 8*ab9b2e15Sgtb * 9*ab9b2e15Sgtb * Export of this software from the United States of America may 10*ab9b2e15Sgtb * require a specific license from the United States Government. 11*ab9b2e15Sgtb * It is the responsibility of any person or organization contemplating 12*ab9b2e15Sgtb * export to obtain such a license before exporting. 13*ab9b2e15Sgtb * 14*ab9b2e15Sgtb * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 15*ab9b2e15Sgtb * distribute this software and its documentation for any purpose and 16*ab9b2e15Sgtb * without fee is hereby granted, provided that the above copyright 17*ab9b2e15Sgtb * notice appear in all copies and that both that copyright notice and 18*ab9b2e15Sgtb * this permission notice appear in supporting documentation, and that 19*ab9b2e15Sgtb * the name of M.I.T. not be used in advertising or publicity pertaining 20*ab9b2e15Sgtb * to distribution of the software without specific, written prior 21*ab9b2e15Sgtb * permission. Furthermore if you modify this software you must label 22*ab9b2e15Sgtb * your software as modified software and not distribute it in such a 23*ab9b2e15Sgtb * fashion that it might be confused with the original M.I.T. software. 24*ab9b2e15Sgtb * M.I.T. makes no representations about the suitability of 25*ab9b2e15Sgtb * this software for any purpose. It is provided "as is" without express 26*ab9b2e15Sgtb * or implied warranty. 27*ab9b2e15Sgtb * 28*ab9b2e15Sgtb */ 29*ab9b2e15Sgtb 30*ab9b2e15Sgtb /* 31*ab9b2e15Sgtb * lucid_context.c - Externalize a "lucid" security 32*ab9b2e15Sgtb * context from a krb5_gss_ctx_id_rec structure. 33*ab9b2e15Sgtb */ 34*ab9b2e15Sgtb #include "gssapiP_krb5.h" 35*ab9b2e15Sgtb #include "gssapi_krb5.h" 36*ab9b2e15Sgtb 37*ab9b2e15Sgtb /* 38*ab9b2e15Sgtb * Local routine prototypes 39*ab9b2e15Sgtb */ 40*ab9b2e15Sgtb static void 41*ab9b2e15Sgtb free_external_lucid_ctx_v1( 42*ab9b2e15Sgtb gss_krb5_lucid_context_v1_t *ctx); 43*ab9b2e15Sgtb 44*ab9b2e15Sgtb static void 45*ab9b2e15Sgtb free_lucid_key_data( 46*ab9b2e15Sgtb gss_krb5_lucid_key_t *key); 47*ab9b2e15Sgtb 48*ab9b2e15Sgtb static krb5_error_code 49*ab9b2e15Sgtb copy_keyblock_to_lucid_key( 50*ab9b2e15Sgtb krb5_keyblock *k5key, 51*ab9b2e15Sgtb gss_krb5_lucid_key_t *lkey); 52*ab9b2e15Sgtb 53*ab9b2e15Sgtb static krb5_error_code 54*ab9b2e15Sgtb make_external_lucid_ctx_v1( 55*ab9b2e15Sgtb krb5_gss_ctx_id_rec * gctx, 56*ab9b2e15Sgtb unsigned int version, 57*ab9b2e15Sgtb void **out_ptr); 58*ab9b2e15Sgtb 59*ab9b2e15Sgtb 60*ab9b2e15Sgtb /* 61*ab9b2e15Sgtb * Exported routines 62*ab9b2e15Sgtb */ 63*ab9b2e15Sgtb 64*ab9b2e15Sgtb OM_uint32 KRB5_CALLCONV 65*ab9b2e15Sgtb gss_krb5int_export_lucid_sec_context( 66*ab9b2e15Sgtb OM_uint32 *minor_status, 67*ab9b2e15Sgtb gss_ctx_id_t *context_handle, 68*ab9b2e15Sgtb OM_uint32 version, 69*ab9b2e15Sgtb void **kctx) 70*ab9b2e15Sgtb { 71*ab9b2e15Sgtb krb5_error_code kret = 0; 72*ab9b2e15Sgtb OM_uint32 retval; 73*ab9b2e15Sgtb krb5_gss_ctx_id_t ctx; 74*ab9b2e15Sgtb void *lctx = NULL; 75*ab9b2e15Sgtb 76*ab9b2e15Sgtb /* Assume failure */ 77*ab9b2e15Sgtb retval = GSS_S_FAILURE; 78*ab9b2e15Sgtb *minor_status = 0; 79*ab9b2e15Sgtb 80*ab9b2e15Sgtb if (kctx) 81*ab9b2e15Sgtb *kctx = NULL; 82*ab9b2e15Sgtb else { 83*ab9b2e15Sgtb kret = EINVAL; 84*ab9b2e15Sgtb goto error_out; 85*ab9b2e15Sgtb } 86*ab9b2e15Sgtb 87*ab9b2e15Sgtb if (!kg_validate_ctx_id(*context_handle)) { 88*ab9b2e15Sgtb kret = (OM_uint32) G_VALIDATE_FAILED; 89*ab9b2e15Sgtb retval = GSS_S_NO_CONTEXT; 90*ab9b2e15Sgtb goto error_out; 91*ab9b2e15Sgtb } 92*ab9b2e15Sgtb 93*ab9b2e15Sgtb ctx = (krb5_gss_ctx_id_t) *context_handle; 94*ab9b2e15Sgtb if (kret) 95*ab9b2e15Sgtb goto error_out; 96*ab9b2e15Sgtb 97*ab9b2e15Sgtb /* Externalize a structure of the right version */ 98*ab9b2e15Sgtb switch (version) { 99*ab9b2e15Sgtb case 1: 100*ab9b2e15Sgtb kret = make_external_lucid_ctx_v1((krb5_pointer)ctx, 101*ab9b2e15Sgtb version, &lctx); 102*ab9b2e15Sgtb break; 103*ab9b2e15Sgtb default: 104*ab9b2e15Sgtb kret = (OM_uint32) KG_LUCID_VERSION; 105*ab9b2e15Sgtb break; 106*ab9b2e15Sgtb } 107*ab9b2e15Sgtb 108*ab9b2e15Sgtb if (kret) 109*ab9b2e15Sgtb goto error_out; 110*ab9b2e15Sgtb 111*ab9b2e15Sgtb /* Success! Record the context and return the buffer */ 112*ab9b2e15Sgtb if (! kg_save_lucidctx_id((void *)lctx)) { 113*ab9b2e15Sgtb kret = G_VALIDATE_FAILED; 114*ab9b2e15Sgtb goto error_out; 115*ab9b2e15Sgtb } 116*ab9b2e15Sgtb 117*ab9b2e15Sgtb *kctx = lctx; 118*ab9b2e15Sgtb *minor_status = 0; 119*ab9b2e15Sgtb retval = GSS_S_COMPLETE; 120*ab9b2e15Sgtb 121*ab9b2e15Sgtb /* Clean up the context state (it is an error for 122*ab9b2e15Sgtb * someone to attempt to use this context again) 123*ab9b2e15Sgtb */ 124*ab9b2e15Sgtb (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL); 125*ab9b2e15Sgtb *context_handle = GSS_C_NO_CONTEXT; 126*ab9b2e15Sgtb 127*ab9b2e15Sgtb return (retval); 128*ab9b2e15Sgtb 129*ab9b2e15Sgtb error_out: 130*ab9b2e15Sgtb if (*minor_status == 0) 131*ab9b2e15Sgtb *minor_status = (OM_uint32) kret; 132*ab9b2e15Sgtb return(retval); 133*ab9b2e15Sgtb } 134*ab9b2e15Sgtb 135*ab9b2e15Sgtb /* 136*ab9b2e15Sgtb * Frees the storage associated with an 137*ab9b2e15Sgtb * exported lucid context structure. 138*ab9b2e15Sgtb */ 139*ab9b2e15Sgtb OM_uint32 KRB5_CALLCONV 140*ab9b2e15Sgtb gss_krb5_free_lucid_sec_context( 141*ab9b2e15Sgtb OM_uint32 *minor_status, 142*ab9b2e15Sgtb void *kctx) 143*ab9b2e15Sgtb { 144*ab9b2e15Sgtb OM_uint32 retval; 145*ab9b2e15Sgtb krb5_error_code kret = 0; 146*ab9b2e15Sgtb int version; 147*ab9b2e15Sgtb 148*ab9b2e15Sgtb /* Assume failure */ 149*ab9b2e15Sgtb retval = GSS_S_FAILURE; 150*ab9b2e15Sgtb *minor_status = 0; 151*ab9b2e15Sgtb 152*ab9b2e15Sgtb if (!kctx) { 153*ab9b2e15Sgtb kret = EINVAL; 154*ab9b2e15Sgtb goto error_out; 155*ab9b2e15Sgtb } 156*ab9b2e15Sgtb 157*ab9b2e15Sgtb /* Verify pointer is valid lucid context */ 158*ab9b2e15Sgtb if (! kg_validate_lucidctx_id(kctx)) { 159*ab9b2e15Sgtb kret = G_VALIDATE_FAILED; 160*ab9b2e15Sgtb goto error_out; 161*ab9b2e15Sgtb } 162*ab9b2e15Sgtb 163*ab9b2e15Sgtb /* Determine version and call correct free routine */ 164*ab9b2e15Sgtb version = ((gss_krb5_lucid_context_version_t *)kctx)->version; 165*ab9b2e15Sgtb switch (version) { 166*ab9b2e15Sgtb case 1: 167*ab9b2e15Sgtb free_external_lucid_ctx_v1((gss_krb5_lucid_context_v1_t*) kctx); 168*ab9b2e15Sgtb break; 169*ab9b2e15Sgtb default: 170*ab9b2e15Sgtb kret = EINVAL; 171*ab9b2e15Sgtb break; 172*ab9b2e15Sgtb } 173*ab9b2e15Sgtb 174*ab9b2e15Sgtb if (kret) 175*ab9b2e15Sgtb goto error_out; 176*ab9b2e15Sgtb 177*ab9b2e15Sgtb /* Success! */ 178*ab9b2e15Sgtb (void)kg_delete_lucidctx_id(kctx); 179*ab9b2e15Sgtb *minor_status = 0; 180*ab9b2e15Sgtb retval = GSS_S_COMPLETE; 181*ab9b2e15Sgtb 182*ab9b2e15Sgtb return (retval); 183*ab9b2e15Sgtb 184*ab9b2e15Sgtb error_out: 185*ab9b2e15Sgtb if (*minor_status == 0) 186*ab9b2e15Sgtb *minor_status = (OM_uint32) kret; 187*ab9b2e15Sgtb return(retval); 188*ab9b2e15Sgtb } 189*ab9b2e15Sgtb 190*ab9b2e15Sgtb /* 191*ab9b2e15Sgtb * Local routines 192*ab9b2e15Sgtb */ 193*ab9b2e15Sgtb 194*ab9b2e15Sgtb static krb5_error_code 195*ab9b2e15Sgtb make_external_lucid_ctx_v1( 196*ab9b2e15Sgtb krb5_gss_ctx_id_rec * gctx, 197*ab9b2e15Sgtb unsigned int version, 198*ab9b2e15Sgtb void **out_ptr) 199*ab9b2e15Sgtb { 200*ab9b2e15Sgtb gss_krb5_lucid_context_v1_t *lctx = NULL; 201*ab9b2e15Sgtb unsigned int bufsize = sizeof(gss_krb5_lucid_context_v1_t); 202*ab9b2e15Sgtb krb5_error_code retval; 203*ab9b2e15Sgtb 204*ab9b2e15Sgtb /* Allocate the structure */ 205*ab9b2e15Sgtb if ((lctx = xmalloc(bufsize)) == NULL) { 206*ab9b2e15Sgtb retval = ENOMEM; 207*ab9b2e15Sgtb goto error_out; 208*ab9b2e15Sgtb } 209*ab9b2e15Sgtb 210*ab9b2e15Sgtb memset(lctx, 0, bufsize); 211*ab9b2e15Sgtb 212*ab9b2e15Sgtb lctx->version = 1; 213*ab9b2e15Sgtb lctx->initiate = gctx->initiate ? 1 : 0; 214*ab9b2e15Sgtb lctx->endtime = gctx->endtime; 215*ab9b2e15Sgtb lctx->send_seq = gctx->seq_send; 216*ab9b2e15Sgtb lctx->recv_seq = gctx->seq_recv; 217*ab9b2e15Sgtb lctx->protocol = gctx->proto; 218*ab9b2e15Sgtb /* gctx->proto == 0 ==> rfc1964-style key information 219*ab9b2e15Sgtb gctx->proto == 1 ==> cfx-style (draft-ietf-krb-wg-gssapi-cfx-07) keys */ 220*ab9b2e15Sgtb if (gctx->proto == 0) { 221*ab9b2e15Sgtb lctx->rfc1964_kd.sign_alg = gctx->signalg; 222*ab9b2e15Sgtb lctx->rfc1964_kd.seal_alg = gctx->sealalg; 223*ab9b2e15Sgtb /* Copy key */ 224*ab9b2e15Sgtb if ((retval = copy_keyblock_to_lucid_key(gctx->subkey, 225*ab9b2e15Sgtb &lctx->rfc1964_kd.ctx_key))) 226*ab9b2e15Sgtb goto error_out; 227*ab9b2e15Sgtb } 228*ab9b2e15Sgtb else if (gctx->proto == 1) { 229*ab9b2e15Sgtb /* Copy keys */ 230*ab9b2e15Sgtb /* (subkey is always present, either a copy of the kerberos 231*ab9b2e15Sgtb session key or a subkey) */ 232*ab9b2e15Sgtb if ((retval = copy_keyblock_to_lucid_key(gctx->subkey, 233*ab9b2e15Sgtb &lctx->cfx_kd.ctx_key))) 234*ab9b2e15Sgtb goto error_out; 235*ab9b2e15Sgtb if (gctx->have_acceptor_subkey) { 236*ab9b2e15Sgtb if ((retval = copy_keyblock_to_lucid_key(gctx->enc, 237*ab9b2e15Sgtb &lctx->cfx_kd.acceptor_subkey))) 238*ab9b2e15Sgtb goto error_out; 239*ab9b2e15Sgtb lctx->cfx_kd.have_acceptor_subkey = 1; 240*ab9b2e15Sgtb } 241*ab9b2e15Sgtb } 242*ab9b2e15Sgtb else { 243*ab9b2e15Sgtb return EINVAL; /* XXX better error code? */ 244*ab9b2e15Sgtb } 245*ab9b2e15Sgtb 246*ab9b2e15Sgtb /* Success! */ 247*ab9b2e15Sgtb *out_ptr = lctx; 248*ab9b2e15Sgtb return 0; 249*ab9b2e15Sgtb 250*ab9b2e15Sgtb error_out: 251*ab9b2e15Sgtb if (lctx) { 252*ab9b2e15Sgtb free_external_lucid_ctx_v1(lctx); 253*ab9b2e15Sgtb } 254*ab9b2e15Sgtb return retval; 255*ab9b2e15Sgtb 256*ab9b2e15Sgtb } 257*ab9b2e15Sgtb 258*ab9b2e15Sgtb /* Copy the contents of a krb5_keyblock to a gss_krb5_lucid_key_t structure */ 259*ab9b2e15Sgtb static krb5_error_code 260*ab9b2e15Sgtb copy_keyblock_to_lucid_key( 261*ab9b2e15Sgtb krb5_keyblock *k5key, 262*ab9b2e15Sgtb gss_krb5_lucid_key_t *lkey) 263*ab9b2e15Sgtb { 264*ab9b2e15Sgtb if (!k5key || !k5key->contents || k5key->length == 0) 265*ab9b2e15Sgtb return EINVAL; 266*ab9b2e15Sgtb 267*ab9b2e15Sgtb memset(lkey, 0, sizeof(gss_krb5_lucid_key_t)); 268*ab9b2e15Sgtb 269*ab9b2e15Sgtb /* Allocate storage for the key data */ 270*ab9b2e15Sgtb if ((lkey->data = xmalloc(k5key->length)) == NULL) { 271*ab9b2e15Sgtb return ENOMEM; 272*ab9b2e15Sgtb } 273*ab9b2e15Sgtb memcpy(lkey->data, k5key->contents, k5key->length); 274*ab9b2e15Sgtb lkey->length = k5key->length; 275*ab9b2e15Sgtb lkey->type = k5key->enctype; 276*ab9b2e15Sgtb 277*ab9b2e15Sgtb return 0; 278*ab9b2e15Sgtb } 279*ab9b2e15Sgtb 280*ab9b2e15Sgtb 281*ab9b2e15Sgtb /* Free any storage associated with a gss_krb5_lucid_key_t structure */ 282*ab9b2e15Sgtb static void 283*ab9b2e15Sgtb free_lucid_key_data( 284*ab9b2e15Sgtb gss_krb5_lucid_key_t *key) 285*ab9b2e15Sgtb { 286*ab9b2e15Sgtb if (key) { 287*ab9b2e15Sgtb if (key->data && key->length) { 288*ab9b2e15Sgtb memset(key->data, 0, key->length); 289*ab9b2e15Sgtb xfree(key->data); 290*ab9b2e15Sgtb memset(key, 0, sizeof(gss_krb5_lucid_key_t)); 291*ab9b2e15Sgtb } 292*ab9b2e15Sgtb } 293*ab9b2e15Sgtb } 294*ab9b2e15Sgtb /* Free any storage associated with a gss_krb5_lucid_context_v1 structure */ 295*ab9b2e15Sgtb static void 296*ab9b2e15Sgtb free_external_lucid_ctx_v1( 297*ab9b2e15Sgtb gss_krb5_lucid_context_v1_t *ctx) 298*ab9b2e15Sgtb { 299*ab9b2e15Sgtb if (ctx) { 300*ab9b2e15Sgtb if (ctx->protocol == 0) { 301*ab9b2e15Sgtb free_lucid_key_data(&ctx->rfc1964_kd.ctx_key); 302*ab9b2e15Sgtb } 303*ab9b2e15Sgtb if (ctx->protocol == 1) { 304*ab9b2e15Sgtb free_lucid_key_data(&ctx->cfx_kd.ctx_key); 305*ab9b2e15Sgtb if (ctx->cfx_kd.have_acceptor_subkey) 306*ab9b2e15Sgtb free_lucid_key_data(&ctx->cfx_kd.acceptor_subkey); 307*ab9b2e15Sgtb } 308*ab9b2e15Sgtb xfree(ctx); 309*ab9b2e15Sgtb ctx = NULL; 310*ab9b2e15Sgtb } 311*ab9b2e15Sgtb } 312