1178825Sdfr/*
2233294Sstas * Copyright (c) 1999 - 2003 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34233294Sstas#include "gsskrb5_locl.h"
35178825Sdfr
36233294SstasOM_uint32 GSSAPI_CALLCONV
37178825Sdfr_gsskrb5_import_sec_context (
38178825Sdfr    OM_uint32 * minor_status,
39178825Sdfr    const gss_buffer_t interprocess_token,
40178825Sdfr    gss_ctx_id_t * context_handle
41178825Sdfr    )
42178825Sdfr{
43178825Sdfr    OM_uint32 ret = GSS_S_FAILURE;
44178825Sdfr    krb5_context context;
45178825Sdfr    krb5_error_code kret;
46178825Sdfr    krb5_storage *sp;
47178825Sdfr    krb5_auth_context ac;
48178825Sdfr    krb5_address local, remote;
49178825Sdfr    krb5_address *localp, *remotep;
50178825Sdfr    krb5_data data;
51178825Sdfr    gss_buffer_desc buffer;
52178825Sdfr    krb5_keyblock keyblock;
53233294Sstas    int32_t flags, tmp;
54178825Sdfr    gsskrb5_ctx ctx;
55178825Sdfr    gss_name_t name;
56178825Sdfr
57178825Sdfr    GSSAPI_KRB5_INIT (&context);
58178825Sdfr
59178825Sdfr    *context_handle = GSS_C_NO_CONTEXT;
60178825Sdfr
61178825Sdfr    localp = remotep = NULL;
62178825Sdfr
63178825Sdfr    sp = krb5_storage_from_mem (interprocess_token->value,
64178825Sdfr				interprocess_token->length);
65178825Sdfr    if (sp == NULL) {
66178825Sdfr	*minor_status = ENOMEM;
67178825Sdfr	return GSS_S_FAILURE;
68178825Sdfr    }
69178825Sdfr
70178825Sdfr    ctx = calloc(1, sizeof(*ctx));
71178825Sdfr    if (ctx == NULL) {
72178825Sdfr	*minor_status = ENOMEM;
73178825Sdfr	krb5_storage_free (sp);
74178825Sdfr	return GSS_S_FAILURE;
75178825Sdfr    }
76178825Sdfr    HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);
77178825Sdfr
78178825Sdfr    kret = krb5_auth_con_init (context,
79178825Sdfr			       &ctx->auth_context);
80178825Sdfr    if (kret) {
81178825Sdfr	*minor_status = kret;
82178825Sdfr	ret = GSS_S_FAILURE;
83178825Sdfr	goto failure;
84178825Sdfr    }
85178825Sdfr
86178825Sdfr    /* flags */
87178825Sdfr
88178825Sdfr    *minor_status = 0;
89178825Sdfr
90178825Sdfr    if (krb5_ret_int32 (sp, &flags) != 0)
91178825Sdfr	goto failure;
92178825Sdfr
93178825Sdfr    /* retrieve the auth context */
94178825Sdfr
95178825Sdfr    ac = ctx->auth_context;
96233294Sstas    if (krb5_ret_int32 (sp, &tmp) != 0)
97178825Sdfr	goto failure;
98233294Sstas    ac->flags = tmp;
99178825Sdfr    if (flags & SC_LOCAL_ADDRESS) {
100178825Sdfr	if (krb5_ret_address (sp, localp = &local) != 0)
101178825Sdfr	    goto failure;
102178825Sdfr    }
103178825Sdfr
104178825Sdfr    if (flags & SC_REMOTE_ADDRESS) {
105178825Sdfr	if (krb5_ret_address (sp, remotep = &remote) != 0)
106178825Sdfr	    goto failure;
107178825Sdfr    }
108178825Sdfr
109178825Sdfr    krb5_auth_con_setaddrs (context, ac, localp, remotep);
110178825Sdfr    if (localp)
111178825Sdfr	krb5_free_address (context, localp);
112178825Sdfr    if (remotep)
113178825Sdfr	krb5_free_address (context, remotep);
114178825Sdfr    localp = remotep = NULL;
115178825Sdfr
116178825Sdfr    if (krb5_ret_int16 (sp, &ac->local_port) != 0)
117178825Sdfr	goto failure;
118178825Sdfr
119178825Sdfr    if (krb5_ret_int16 (sp, &ac->remote_port) != 0)
120178825Sdfr	goto failure;
121178825Sdfr    if (flags & SC_KEYBLOCK) {
122178825Sdfr	if (krb5_ret_keyblock (sp, &keyblock) != 0)
123178825Sdfr	    goto failure;
124178825Sdfr	krb5_auth_con_setkey (context, ac, &keyblock);
125178825Sdfr	krb5_free_keyblock_contents (context, &keyblock);
126178825Sdfr    }
127178825Sdfr    if (flags & SC_LOCAL_SUBKEY) {
128178825Sdfr	if (krb5_ret_keyblock (sp, &keyblock) != 0)
129178825Sdfr	    goto failure;
130178825Sdfr	krb5_auth_con_setlocalsubkey (context, ac, &keyblock);
131178825Sdfr	krb5_free_keyblock_contents (context, &keyblock);
132178825Sdfr    }
133178825Sdfr    if (flags & SC_REMOTE_SUBKEY) {
134178825Sdfr	if (krb5_ret_keyblock (sp, &keyblock) != 0)
135178825Sdfr	    goto failure;
136178825Sdfr	krb5_auth_con_setremotesubkey (context, ac, &keyblock);
137178825Sdfr	krb5_free_keyblock_contents (context, &keyblock);
138178825Sdfr    }
139178825Sdfr    if (krb5_ret_uint32 (sp, &ac->local_seqnumber))
140178825Sdfr	goto failure;
141178825Sdfr    if (krb5_ret_uint32 (sp, &ac->remote_seqnumber))
142178825Sdfr	goto failure;
143178825Sdfr
144178825Sdfr    if (krb5_ret_int32 (sp, &tmp) != 0)
145178825Sdfr	goto failure;
146178825Sdfr    ac->keytype = tmp;
147178825Sdfr    if (krb5_ret_int32 (sp, &tmp) != 0)
148178825Sdfr	goto failure;
149178825Sdfr    ac->cksumtype = tmp;
150178825Sdfr
151178825Sdfr    /* names */
152178825Sdfr
153178825Sdfr    if (krb5_ret_data (sp, &data))
154178825Sdfr	goto failure;
155178825Sdfr    buffer.value  = data.data;
156178825Sdfr    buffer.length = data.length;
157178825Sdfr
158178825Sdfr    ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
159178825Sdfr				&name);
160178825Sdfr    if (ret) {
161178825Sdfr	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID,
162178825Sdfr				    &name);
163178825Sdfr	if (ret) {
164178825Sdfr	    krb5_data_free (&data);
165178825Sdfr	    goto failure;
166178825Sdfr	}
167178825Sdfr    }
168178825Sdfr    ctx->source = (krb5_principal)name;
169178825Sdfr    krb5_data_free (&data);
170178825Sdfr
171178825Sdfr    if (krb5_ret_data (sp, &data) != 0)
172178825Sdfr	goto failure;
173178825Sdfr    buffer.value  = data.data;
174178825Sdfr    buffer.length = data.length;
175178825Sdfr
176178825Sdfr    ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
177178825Sdfr				&name);
178178825Sdfr    if (ret) {
179178825Sdfr	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID,
180178825Sdfr				    &name);
181178825Sdfr	if (ret) {
182178825Sdfr	    krb5_data_free (&data);
183178825Sdfr	    goto failure;
184178825Sdfr	}
185233294Sstas    }
186178825Sdfr    ctx->target = (krb5_principal)name;
187178825Sdfr    krb5_data_free (&data);
188178825Sdfr
189178825Sdfr    if (krb5_ret_int32 (sp, &tmp))
190178825Sdfr	goto failure;
191178825Sdfr    ctx->flags = tmp;
192178825Sdfr    if (krb5_ret_int32 (sp, &tmp))
193178825Sdfr	goto failure;
194178825Sdfr    ctx->more_flags = tmp;
195178825Sdfr    if (krb5_ret_int32 (sp, &tmp))
196178825Sdfr	goto failure;
197178825Sdfr    ctx->lifetime = tmp;
198178825Sdfr
199178825Sdfr    ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order);
200178825Sdfr    if (ret)
201233294Sstas        goto failure;
202233294Sstas
203178825Sdfr    krb5_storage_free (sp);
204178825Sdfr
205233294Sstas    _gsskrb5i_is_cfx(context, ctx, (ctx->more_flags & LOCAL) == 0);
206233294Sstas
207178825Sdfr    *context_handle = (gss_ctx_id_t)ctx;
208178825Sdfr
209178825Sdfr    return GSS_S_COMPLETE;
210178825Sdfr
211178825Sdfrfailure:
212178825Sdfr    krb5_auth_con_free (context,
213178825Sdfr			ctx->auth_context);
214178825Sdfr    if (ctx->source != NULL)
215178825Sdfr	krb5_free_principal(context, ctx->source);
216178825Sdfr    if (ctx->target != NULL)
217178825Sdfr	krb5_free_principal(context, ctx->target);
218178825Sdfr    if (localp)
219178825Sdfr	krb5_free_address (context, localp);
220178825Sdfr    if (remotep)
221178825Sdfr	krb5_free_address (context, remotep);
222178825Sdfr    if(ctx->order)
223178825Sdfr	_gssapi_msg_order_destroy(&ctx->order);
224178825Sdfr    HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
225178825Sdfr    krb5_storage_free (sp);
226178825Sdfr    free (ctx);
227178825Sdfr    *context_handle = GSS_C_NO_CONTEXT;
228178825Sdfr    return ret;
229178825Sdfr}
230