1*10598SGlenn.Barry@Sun.COM /*
2*10598SGlenn.Barry@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3*10598SGlenn.Barry@Sun.COM * Use is subject to license terms.
4*10598SGlenn.Barry@Sun.COM */
5*10598SGlenn.Barry@Sun.COM /* -*- mode: c; indent-tabs-mode: nil -*- */
65053Sgtb /*
75053Sgtb * lib/gssapi/krb5/lucid_context.c
85053Sgtb *
9*10598SGlenn.Barry@Sun.COM * Copyright 2004, 2008 by the Massachusetts Institute of Technology.
105053Sgtb * All Rights Reserved.
115053Sgtb *
125053Sgtb * Export of this software from the United States of America may
135053Sgtb * require a specific license from the United States Government.
145053Sgtb * It is the responsibility of any person or organization contemplating
155053Sgtb * export to obtain such a license before exporting.
165053Sgtb *
175053Sgtb * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
185053Sgtb * distribute this software and its documentation for any purpose and
195053Sgtb * without fee is hereby granted, provided that the above copyright
205053Sgtb * notice appear in all copies and that both that copyright notice and
215053Sgtb * this permission notice appear in supporting documentation, and that
225053Sgtb * the name of M.I.T. not be used in advertising or publicity pertaining
235053Sgtb * to distribution of the software without specific, written prior
245053Sgtb * permission. Furthermore if you modify this software you must label
255053Sgtb * your software as modified software and not distribute it in such a
265053Sgtb * fashion that it might be confused with the original M.I.T. software.
275053Sgtb * M.I.T. makes no representations about the suitability of
285053Sgtb * this software for any purpose. It is provided "as is" without express
295053Sgtb * or implied warranty.
305053Sgtb *
315053Sgtb */
325053Sgtb
335053Sgtb /*
345053Sgtb * lucid_context.c - Externalize a "lucid" security
355053Sgtb * context from a krb5_gss_ctx_id_rec structure.
365053Sgtb */
375053Sgtb #include "gssapiP_krb5.h"
385053Sgtb #include "gssapi_krb5.h"
39*10598SGlenn.Barry@Sun.COM #include "mechglueP.h" /* SUNW17PACresync */
405053Sgtb
415053Sgtb /*
425053Sgtb * Local routine prototypes
435053Sgtb */
445053Sgtb static void
455053Sgtb free_external_lucid_ctx_v1(
465053Sgtb gss_krb5_lucid_context_v1_t *ctx);
475053Sgtb
485053Sgtb static void
495053Sgtb free_lucid_key_data(
505053Sgtb gss_krb5_lucid_key_t *key);
515053Sgtb
525053Sgtb static krb5_error_code
535053Sgtb copy_keyblock_to_lucid_key(
545053Sgtb krb5_keyblock *k5key,
555053Sgtb gss_krb5_lucid_key_t *lkey);
565053Sgtb
575053Sgtb static krb5_error_code
585053Sgtb make_external_lucid_ctx_v1(
595053Sgtb krb5_gss_ctx_id_rec * gctx,
60*10598SGlenn.Barry@Sun.COM int version,
615053Sgtb void **out_ptr);
625053Sgtb
635053Sgtb
645053Sgtb /*
655053Sgtb * Exported routines
665053Sgtb */
675053Sgtb
685053Sgtb OM_uint32 KRB5_CALLCONV
gss_krb5int_export_lucid_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,const gss_OID desired_object,gss_buffer_set_t * data_set)695053Sgtb gss_krb5int_export_lucid_sec_context(
70*10598SGlenn.Barry@Sun.COM OM_uint32 *minor_status,
71*10598SGlenn.Barry@Sun.COM gss_ctx_id_t context_handle,
72*10598SGlenn.Barry@Sun.COM const gss_OID desired_object,
73*10598SGlenn.Barry@Sun.COM gss_buffer_set_t *data_set)
745053Sgtb {
75*10598SGlenn.Barry@Sun.COM krb5_error_code kret = 0;
76*10598SGlenn.Barry@Sun.COM OM_uint32 retval;
77*10598SGlenn.Barry@Sun.COM krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle;
78*10598SGlenn.Barry@Sun.COM void *lctx = NULL;
79*10598SGlenn.Barry@Sun.COM int version = 0;
80*10598SGlenn.Barry@Sun.COM gss_buffer_desc rep;
815053Sgtb
825053Sgtb /* Assume failure */
835053Sgtb retval = GSS_S_FAILURE;
845053Sgtb *minor_status = 0;
85*10598SGlenn.Barry@Sun.COM *data_set = GSS_C_NO_BUFFER_SET;
865053Sgtb
87*10598SGlenn.Barry@Sun.COM retval = generic_gss_oid_decompose(minor_status,
88*10598SGlenn.Barry@Sun.COM GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
89*10598SGlenn.Barry@Sun.COM GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,
90*10598SGlenn.Barry@Sun.COM desired_object,
91*10598SGlenn.Barry@Sun.COM &version);
92*10598SGlenn.Barry@Sun.COM if (GSS_ERROR(retval))
93*10598SGlenn.Barry@Sun.COM return retval;
945053Sgtb
955053Sgtb /* Externalize a structure of the right version */
965053Sgtb switch (version) {
975053Sgtb case 1:
98*10598SGlenn.Barry@Sun.COM kret = make_external_lucid_ctx_v1((krb5_pointer)ctx,
99*10598SGlenn.Barry@Sun.COM version, &lctx);
1005053Sgtb break;
1015053Sgtb default:
102*10598SGlenn.Barry@Sun.COM kret = (OM_uint32) KG_LUCID_VERSION;
103*10598SGlenn.Barry@Sun.COM break;
1045053Sgtb }
1055053Sgtb
1065053Sgtb if (kret)
107*10598SGlenn.Barry@Sun.COM goto error_out;
1085053Sgtb
1095053Sgtb /* Success! Record the context and return the buffer */
1105053Sgtb if (! kg_save_lucidctx_id((void *)lctx)) {
111*10598SGlenn.Barry@Sun.COM kret = G_VALIDATE_FAILED;
112*10598SGlenn.Barry@Sun.COM goto error_out;
1135053Sgtb }
1145053Sgtb
115*10598SGlenn.Barry@Sun.COM rep.value = &lctx;
116*10598SGlenn.Barry@Sun.COM rep.length = sizeof(lctx);
1175053Sgtb
118*10598SGlenn.Barry@Sun.COM retval = generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
119*10598SGlenn.Barry@Sun.COM if (GSS_ERROR(retval))
120*10598SGlenn.Barry@Sun.COM goto error_out;
1215053Sgtb
1225053Sgtb error_out:
123*10598SGlenn.Barry@Sun.COM if (*minor_status == 0)
124*10598SGlenn.Barry@Sun.COM *minor_status = (OM_uint32) kret;
1255053Sgtb return(retval);
1265053Sgtb }
1275053Sgtb
1285053Sgtb /*
1295053Sgtb * Frees the storage associated with an
1305053Sgtb * exported lucid context structure.
1315053Sgtb */
132*10598SGlenn.Barry@Sun.COM OM_uint32
gss_krb5int_free_lucid_sec_context(OM_uint32 * minor_status,const gss_OID desired_mech,const gss_OID desired_object,gss_buffer_t value)133*10598SGlenn.Barry@Sun.COM gss_krb5int_free_lucid_sec_context(
1345053Sgtb OM_uint32 *minor_status,
135*10598SGlenn.Barry@Sun.COM const gss_OID desired_mech,
136*10598SGlenn.Barry@Sun.COM const gss_OID desired_object,
137*10598SGlenn.Barry@Sun.COM gss_buffer_t value)
1385053Sgtb {
139*10598SGlenn.Barry@Sun.COM OM_uint32 retval;
140*10598SGlenn.Barry@Sun.COM krb5_error_code kret = 0;
141*10598SGlenn.Barry@Sun.COM int version;
142*10598SGlenn.Barry@Sun.COM void *kctx;
1435053Sgtb
1445053Sgtb /* Assume failure */
1455053Sgtb retval = GSS_S_FAILURE;
1465053Sgtb *minor_status = 0;
1475053Sgtb
148*10598SGlenn.Barry@Sun.COM kctx = value->value;
1495053Sgtb if (!kctx) {
150*10598SGlenn.Barry@Sun.COM kret = EINVAL;
151*10598SGlenn.Barry@Sun.COM goto error_out;
1525053Sgtb }
1535053Sgtb
1545053Sgtb /* Verify pointer is valid lucid context */
1555053Sgtb if (! kg_validate_lucidctx_id(kctx)) {
156*10598SGlenn.Barry@Sun.COM kret = G_VALIDATE_FAILED;
157*10598SGlenn.Barry@Sun.COM goto error_out;
1585053Sgtb }
1595053Sgtb
1605053Sgtb /* Determine version and call correct free routine */
1615053Sgtb version = ((gss_krb5_lucid_context_version_t *)kctx)->version;
1625053Sgtb switch (version) {
1635053Sgtb case 1:
164*10598SGlenn.Barry@Sun.COM (void)kg_delete_lucidctx_id(kctx);
165*10598SGlenn.Barry@Sun.COM free_external_lucid_ctx_v1((gss_krb5_lucid_context_v1_t*) kctx);
166*10598SGlenn.Barry@Sun.COM break;
1675053Sgtb default:
168*10598SGlenn.Barry@Sun.COM kret = EINVAL;
169*10598SGlenn.Barry@Sun.COM break;
1705053Sgtb }
1715053Sgtb
1725053Sgtb if (kret)
173*10598SGlenn.Barry@Sun.COM goto error_out;
1745053Sgtb
1755053Sgtb /* Success! */
1765053Sgtb *minor_status = 0;
1775053Sgtb retval = GSS_S_COMPLETE;
1785053Sgtb
1795053Sgtb return (retval);
1805053Sgtb
1815053Sgtb error_out:
182*10598SGlenn.Barry@Sun.COM if (*minor_status == 0)
183*10598SGlenn.Barry@Sun.COM *minor_status = (OM_uint32) kret;
1845053Sgtb return(retval);
1855053Sgtb }
1865053Sgtb
1875053Sgtb /*
1885053Sgtb * Local routines
1895053Sgtb */
1905053Sgtb
1915053Sgtb static krb5_error_code
make_external_lucid_ctx_v1(krb5_gss_ctx_id_rec * gctx,int version,void ** out_ptr)1925053Sgtb make_external_lucid_ctx_v1(
1935053Sgtb krb5_gss_ctx_id_rec * gctx,
194*10598SGlenn.Barry@Sun.COM int version,
1955053Sgtb void **out_ptr)
1965053Sgtb {
1975053Sgtb gss_krb5_lucid_context_v1_t *lctx = NULL;
1985053Sgtb unsigned int bufsize = sizeof(gss_krb5_lucid_context_v1_t);
1995053Sgtb krb5_error_code retval;
2005053Sgtb
2015053Sgtb /* Allocate the structure */
2025053Sgtb if ((lctx = xmalloc(bufsize)) == NULL) {
203*10598SGlenn.Barry@Sun.COM retval = ENOMEM;
204*10598SGlenn.Barry@Sun.COM goto error_out;
2055053Sgtb }
2065053Sgtb
2075053Sgtb memset(lctx, 0, bufsize);
2085053Sgtb
2095053Sgtb lctx->version = 1;
2105053Sgtb lctx->initiate = gctx->initiate ? 1 : 0;
211*10598SGlenn.Barry@Sun.COM lctx->endtime = gctx->krb_times.endtime;
2125053Sgtb lctx->send_seq = gctx->seq_send;
2135053Sgtb lctx->recv_seq = gctx->seq_recv;
2145053Sgtb lctx->protocol = gctx->proto;
2155053Sgtb /* gctx->proto == 0 ==> rfc1964-style key information
2165053Sgtb gctx->proto == 1 ==> cfx-style (draft-ietf-krb-wg-gssapi-cfx-07) keys */
2175053Sgtb if (gctx->proto == 0) {
218*10598SGlenn.Barry@Sun.COM lctx->rfc1964_kd.sign_alg = gctx->signalg;
219*10598SGlenn.Barry@Sun.COM lctx->rfc1964_kd.seal_alg = gctx->sealalg;
220*10598SGlenn.Barry@Sun.COM /* Copy key */
221*10598SGlenn.Barry@Sun.COM if ((retval = copy_keyblock_to_lucid_key(gctx->seq,
222*10598SGlenn.Barry@Sun.COM &lctx->rfc1964_kd.ctx_key)))
223*10598SGlenn.Barry@Sun.COM goto error_out;
2245053Sgtb }
2255053Sgtb else if (gctx->proto == 1) {
226*10598SGlenn.Barry@Sun.COM /* Copy keys */
227*10598SGlenn.Barry@Sun.COM /* (subkey is always present, either a copy of the kerberos
228*10598SGlenn.Barry@Sun.COM session key or a subkey) */
229*10598SGlenn.Barry@Sun.COM if ((retval = copy_keyblock_to_lucid_key(gctx->subkey,
230*10598SGlenn.Barry@Sun.COM &lctx->cfx_kd.ctx_key)))
231*10598SGlenn.Barry@Sun.COM goto error_out;
232*10598SGlenn.Barry@Sun.COM if (gctx->have_acceptor_subkey) {
233*10598SGlenn.Barry@Sun.COM if ((retval = copy_keyblock_to_lucid_key(gctx->acceptor_subkey,
234*10598SGlenn.Barry@Sun.COM &lctx->cfx_kd.acceptor_subkey)))
235*10598SGlenn.Barry@Sun.COM goto error_out;
236*10598SGlenn.Barry@Sun.COM lctx->cfx_kd.have_acceptor_subkey = 1;
237*10598SGlenn.Barry@Sun.COM }
2385053Sgtb }
2395053Sgtb else {
240*10598SGlenn.Barry@Sun.COM return EINVAL; /* XXX better error code? */
2415053Sgtb }
2425053Sgtb
2435053Sgtb /* Success! */
2445053Sgtb *out_ptr = lctx;
2455053Sgtb return 0;
2465053Sgtb
2475053Sgtb error_out:
2485053Sgtb if (lctx) {
249*10598SGlenn.Barry@Sun.COM free_external_lucid_ctx_v1(lctx);
2505053Sgtb }
2515053Sgtb return retval;
2525053Sgtb
2535053Sgtb }
2545053Sgtb
2555053Sgtb /* Copy the contents of a krb5_keyblock to a gss_krb5_lucid_key_t structure */
2565053Sgtb static krb5_error_code
copy_keyblock_to_lucid_key(krb5_keyblock * k5key,gss_krb5_lucid_key_t * lkey)2575053Sgtb copy_keyblock_to_lucid_key(
2585053Sgtb krb5_keyblock *k5key,
2595053Sgtb gss_krb5_lucid_key_t *lkey)
2605053Sgtb {
2615053Sgtb if (!k5key || !k5key->contents || k5key->length == 0)
262*10598SGlenn.Barry@Sun.COM return EINVAL;
2635053Sgtb
2645053Sgtb memset(lkey, 0, sizeof(gss_krb5_lucid_key_t));
2655053Sgtb
2665053Sgtb /* Allocate storage for the key data */
2675053Sgtb if ((lkey->data = xmalloc(k5key->length)) == NULL) {
268*10598SGlenn.Barry@Sun.COM return ENOMEM;
2695053Sgtb }
2705053Sgtb memcpy(lkey->data, k5key->contents, k5key->length);
2715053Sgtb lkey->length = k5key->length;
2725053Sgtb lkey->type = k5key->enctype;
2735053Sgtb
2745053Sgtb return 0;
2755053Sgtb }
2765053Sgtb
2775053Sgtb
2785053Sgtb /* Free any storage associated with a gss_krb5_lucid_key_t structure */
2795053Sgtb static void
free_lucid_key_data(gss_krb5_lucid_key_t * key)2805053Sgtb free_lucid_key_data(
2815053Sgtb gss_krb5_lucid_key_t *key)
2825053Sgtb {
2835053Sgtb if (key) {
284*10598SGlenn.Barry@Sun.COM if (key->data && key->length) {
285*10598SGlenn.Barry@Sun.COM memset(key->data, 0, key->length);
286*10598SGlenn.Barry@Sun.COM xfree(key->data);
287*10598SGlenn.Barry@Sun.COM memset(key, 0, sizeof(gss_krb5_lucid_key_t));
288*10598SGlenn.Barry@Sun.COM }
2895053Sgtb }
2905053Sgtb }
2915053Sgtb /* Free any storage associated with a gss_krb5_lucid_context_v1 structure */
2925053Sgtb static void
free_external_lucid_ctx_v1(gss_krb5_lucid_context_v1_t * ctx)2935053Sgtb free_external_lucid_ctx_v1(
2945053Sgtb gss_krb5_lucid_context_v1_t *ctx)
2955053Sgtb {
2965053Sgtb if (ctx) {
297*10598SGlenn.Barry@Sun.COM if (ctx->protocol == 0) {
298*10598SGlenn.Barry@Sun.COM free_lucid_key_data(&ctx->rfc1964_kd.ctx_key);
299*10598SGlenn.Barry@Sun.COM }
300*10598SGlenn.Barry@Sun.COM if (ctx->protocol == 1) {
301*10598SGlenn.Barry@Sun.COM free_lucid_key_data(&ctx->cfx_kd.ctx_key);
302*10598SGlenn.Barry@Sun.COM if (ctx->cfx_kd.have_acceptor_subkey)
303*10598SGlenn.Barry@Sun.COM free_lucid_key_data(&ctx->cfx_kd.acceptor_subkey);
304*10598SGlenn.Barry@Sun.COM }
305*10598SGlenn.Barry@Sun.COM xfree(ctx);
306*10598SGlenn.Barry@Sun.COM ctx = NULL;
3075053Sgtb }
3085053Sgtb }
309