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