export_sec_context.c revision 178825
1178825Sdfr/*
2178825Sdfr * Copyright (c) 1999 - 2003 Kungliga Tekniska H�gskolan
3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden).
4178825Sdfr * All rights reserved.
5178825Sdfr *
6178825Sdfr * Redistribution and use in source and binary forms, with or without
7178825Sdfr * modification, are permitted provided that the following conditions
8178825Sdfr * are met:
9178825Sdfr *
10178825Sdfr * 1. Redistributions of source code must retain the above copyright
11178825Sdfr *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
14178825Sdfr *    notice, this list of conditions and the following disclaimer in the
15178825Sdfr *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors
18178825Sdfr *    may be used to endorse or promote products derived from this software
19178825Sdfr *    without specific prior written permission.
20178825Sdfr *
21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31178825Sdfr * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#include "krb5/gsskrb5_locl.h"
35178825Sdfr
36178825SdfrRCSID("$Id: export_sec_context.c 19031 2006-11-13 18:02:57Z lha $");
37178825Sdfr
38178825SdfrOM_uint32
39178825Sdfr_gsskrb5_export_sec_context (
40178825Sdfr    OM_uint32 * minor_status,
41178825Sdfr    gss_ctx_id_t * context_handle,
42178825Sdfr    gss_buffer_t interprocess_token
43178825Sdfr    )
44178825Sdfr{
45178825Sdfr    krb5_context context;
46178825Sdfr    const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle;
47178825Sdfr    krb5_storage *sp;
48178825Sdfr    krb5_auth_context ac;
49178825Sdfr    OM_uint32 ret = GSS_S_COMPLETE;
50178825Sdfr    krb5_data data;
51178825Sdfr    gss_buffer_desc buffer;
52178825Sdfr    int flags;
53178825Sdfr    OM_uint32 minor;
54178825Sdfr    krb5_error_code kret;
55178825Sdfr
56178825Sdfr    GSSAPI_KRB5_INIT (&context);
57178825Sdfr
58178825Sdfr    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
59178825Sdfr
60178825Sdfr    if (!(ctx->flags & GSS_C_TRANS_FLAG)) {
61178825Sdfr	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
62178825Sdfr	*minor_status = 0;
63178825Sdfr	return GSS_S_UNAVAILABLE;
64178825Sdfr    }
65178825Sdfr
66178825Sdfr    sp = krb5_storage_emem ();
67178825Sdfr    if (sp == NULL) {
68178825Sdfr	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
69178825Sdfr	*minor_status = ENOMEM;
70178825Sdfr	return GSS_S_FAILURE;
71178825Sdfr    }
72178825Sdfr    ac = ctx->auth_context;
73178825Sdfr
74178825Sdfr    /* flagging included fields */
75178825Sdfr
76178825Sdfr    flags = 0;
77178825Sdfr    if (ac->local_address)
78178825Sdfr	flags |= SC_LOCAL_ADDRESS;
79178825Sdfr    if (ac->remote_address)
80178825Sdfr	flags |= SC_REMOTE_ADDRESS;
81178825Sdfr    if (ac->keyblock)
82178825Sdfr	flags |= SC_KEYBLOCK;
83178825Sdfr    if (ac->local_subkey)
84178825Sdfr	flags |= SC_LOCAL_SUBKEY;
85178825Sdfr    if (ac->remote_subkey)
86178825Sdfr	flags |= SC_REMOTE_SUBKEY;
87178825Sdfr
88178825Sdfr    kret = krb5_store_int32 (sp, flags);
89178825Sdfr    if (kret) {
90178825Sdfr	*minor_status = kret;
91178825Sdfr	goto failure;
92178825Sdfr    }
93178825Sdfr
94178825Sdfr    /* marshall auth context */
95178825Sdfr
96178825Sdfr    kret = krb5_store_int32 (sp, ac->flags);
97178825Sdfr    if (kret) {
98178825Sdfr	*minor_status = kret;
99178825Sdfr	goto failure;
100178825Sdfr    }
101178825Sdfr    if (ac->local_address) {
102178825Sdfr	kret = krb5_store_address (sp, *ac->local_address);
103178825Sdfr	if (kret) {
104178825Sdfr	    *minor_status = kret;
105178825Sdfr	    goto failure;
106178825Sdfr	}
107178825Sdfr    }
108178825Sdfr    if (ac->remote_address) {
109178825Sdfr	kret = krb5_store_address (sp, *ac->remote_address);
110178825Sdfr	if (kret) {
111178825Sdfr	    *minor_status = kret;
112178825Sdfr	    goto failure;
113178825Sdfr	}
114178825Sdfr    }
115178825Sdfr    kret = krb5_store_int16 (sp, ac->local_port);
116178825Sdfr    if (kret) {
117178825Sdfr	*minor_status = kret;
118178825Sdfr	goto failure;
119178825Sdfr    }
120178825Sdfr    kret = krb5_store_int16 (sp, ac->remote_port);
121178825Sdfr    if (kret) {
122178825Sdfr	*minor_status = kret;
123178825Sdfr	goto failure;
124178825Sdfr    }
125178825Sdfr    if (ac->keyblock) {
126178825Sdfr	kret = krb5_store_keyblock (sp, *ac->keyblock);
127178825Sdfr	if (kret) {
128178825Sdfr	    *minor_status = kret;
129178825Sdfr	    goto failure;
130178825Sdfr	}
131178825Sdfr    }
132178825Sdfr    if (ac->local_subkey) {
133178825Sdfr	kret = krb5_store_keyblock (sp, *ac->local_subkey);
134178825Sdfr	if (kret) {
135178825Sdfr	    *minor_status = kret;
136178825Sdfr	    goto failure;
137178825Sdfr	}
138178825Sdfr    }
139178825Sdfr    if (ac->remote_subkey) {
140178825Sdfr	kret = krb5_store_keyblock (sp, *ac->remote_subkey);
141178825Sdfr	if (kret) {
142178825Sdfr	    *minor_status = kret;
143178825Sdfr	    goto failure;
144178825Sdfr	}
145178825Sdfr    }
146178825Sdfr    kret = krb5_store_int32 (sp, ac->local_seqnumber);
147178825Sdfr	if (kret) {
148178825Sdfr	    *minor_status = kret;
149178825Sdfr	    goto failure;
150178825Sdfr	}
151178825Sdfr    kret = krb5_store_int32 (sp, ac->remote_seqnumber);
152178825Sdfr	if (kret) {
153178825Sdfr	    *minor_status = kret;
154178825Sdfr	    goto failure;
155178825Sdfr	}
156178825Sdfr
157178825Sdfr    kret = krb5_store_int32 (sp, ac->keytype);
158178825Sdfr    if (kret) {
159178825Sdfr	*minor_status = kret;
160178825Sdfr	goto failure;
161178825Sdfr    }
162178825Sdfr    kret = krb5_store_int32 (sp, ac->cksumtype);
163178825Sdfr    if (kret) {
164178825Sdfr	*minor_status = kret;
165178825Sdfr	goto failure;
166178825Sdfr    }
167178825Sdfr
168178825Sdfr    /* names */
169178825Sdfr
170178825Sdfr    ret = _gsskrb5_export_name (minor_status,
171178825Sdfr				(gss_name_t)ctx->source, &buffer);
172178825Sdfr    if (ret)
173178825Sdfr	goto failure;
174178825Sdfr    data.data   = buffer.value;
175178825Sdfr    data.length = buffer.length;
176178825Sdfr    kret = krb5_store_data (sp, data);
177178825Sdfr    _gsskrb5_release_buffer (&minor, &buffer);
178178825Sdfr    if (kret) {
179178825Sdfr	*minor_status = kret;
180178825Sdfr	goto failure;
181178825Sdfr    }
182178825Sdfr
183178825Sdfr    ret = _gsskrb5_export_name (minor_status,
184178825Sdfr				(gss_name_t)ctx->target, &buffer);
185178825Sdfr    if (ret)
186178825Sdfr	goto failure;
187178825Sdfr    data.data   = buffer.value;
188178825Sdfr    data.length = buffer.length;
189178825Sdfr
190178825Sdfr    ret = GSS_S_FAILURE;
191178825Sdfr
192178825Sdfr    kret = krb5_store_data (sp, data);
193178825Sdfr    _gsskrb5_release_buffer (&minor, &buffer);
194178825Sdfr    if (kret) {
195178825Sdfr	*minor_status = kret;
196178825Sdfr	goto failure;
197178825Sdfr    }
198178825Sdfr
199178825Sdfr    kret = krb5_store_int32 (sp, ctx->flags);
200178825Sdfr    if (kret) {
201178825Sdfr	*minor_status = kret;
202178825Sdfr	goto failure;
203178825Sdfr    }
204178825Sdfr    kret = krb5_store_int32 (sp, ctx->more_flags);
205178825Sdfr    if (kret) {
206178825Sdfr	*minor_status = kret;
207178825Sdfr	goto failure;
208178825Sdfr    }
209178825Sdfr    kret = krb5_store_int32 (sp, ctx->lifetime);
210178825Sdfr    if (kret) {
211178825Sdfr	*minor_status = kret;
212178825Sdfr	goto failure;
213178825Sdfr    }
214178825Sdfr    kret = _gssapi_msg_order_export(sp, ctx->order);
215178825Sdfr    if (kret ) {
216178825Sdfr        *minor_status = kret;
217178825Sdfr        goto failure;
218178825Sdfr    }
219178825Sdfr
220178825Sdfr    kret = krb5_storage_to_data (sp, &data);
221178825Sdfr    krb5_storage_free (sp);
222178825Sdfr    if (kret) {
223178825Sdfr	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
224178825Sdfr	*minor_status = kret;
225178825Sdfr	return GSS_S_FAILURE;
226178825Sdfr    }
227178825Sdfr    interprocess_token->length = data.length;
228178825Sdfr    interprocess_token->value  = data.data;
229178825Sdfr    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
230178825Sdfr    ret = _gsskrb5_delete_sec_context (minor_status, context_handle,
231178825Sdfr				       GSS_C_NO_BUFFER);
232178825Sdfr    if (ret != GSS_S_COMPLETE)
233178825Sdfr	_gsskrb5_release_buffer (NULL, interprocess_token);
234178825Sdfr    *minor_status = 0;
235178825Sdfr    return ret;
236178825Sdfr failure:
237178825Sdfr    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
238178825Sdfr    krb5_storage_free (sp);
239178825Sdfr    return ret;
240178825Sdfr}
241