1 /*
2  * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "gsskrb5_locl.h"
35 
36 OM_uint32 GSSAPI_CALLCONV
37 _gsskrb5_import_sec_context (
38     OM_uint32 * minor_status,
39     const gss_buffer_t interprocess_token,
40     gss_ctx_id_t * context_handle
41     )
42 {
43     OM_uint32 ret = GSS_S_FAILURE;
44     krb5_context context;
45     krb5_error_code kret;
46     krb5_storage *sp;
47     krb5_auth_context ac;
48     krb5_address local, remote;
49     krb5_address *localp, *remotep;
50     krb5_data data;
51     gss_buffer_desc buffer;
52     krb5_keyblock keyblock;
53     int32_t flags, tmp;
54     gsskrb5_ctx ctx;
55     gss_name_t name;
56 
57     GSSAPI_KRB5_INIT (&context);
58 
59     *context_handle = GSS_C_NO_CONTEXT;
60 
61     localp = remotep = NULL;
62 
63     sp = krb5_storage_from_mem (interprocess_token->value,
64 				interprocess_token->length);
65     if (sp == NULL) {
66 	*minor_status = ENOMEM;
67 	return GSS_S_FAILURE;
68     }
69 
70     ctx = calloc(1, sizeof(*ctx));
71     if (ctx == NULL) {
72 	*minor_status = ENOMEM;
73 	krb5_storage_free (sp);
74 	return GSS_S_FAILURE;
75     }
76     HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);
77 
78     kret = krb5_auth_con_init (context,
79 			       &ctx->auth_context);
80     if (kret) {
81 	*minor_status = kret;
82 	ret = GSS_S_FAILURE;
83 	goto failure;
84     }
85 
86     /* flags */
87 
88     *minor_status = 0;
89 
90     if (krb5_ret_int32 (sp, &flags) != 0)
91 	goto failure;
92 
93     /* retrieve the auth context */
94 
95     ac = ctx->auth_context;
96     if (krb5_ret_int32 (sp, &tmp) != 0)
97 	goto failure;
98     ac->flags = tmp;
99     if (flags & SC_LOCAL_ADDRESS) {
100 	if (krb5_ret_address (sp, localp = &local) != 0)
101 	    goto failure;
102     }
103 
104     if (flags & SC_REMOTE_ADDRESS) {
105 	if (krb5_ret_address (sp, remotep = &remote) != 0)
106 	    goto failure;
107     }
108 
109     krb5_auth_con_setaddrs (context, ac, localp, remotep);
110     if (localp)
111 	krb5_free_address (context, localp);
112     if (remotep)
113 	krb5_free_address (context, remotep);
114     localp = remotep = NULL;
115 
116     if (krb5_ret_int16 (sp, &ac->local_port) != 0)
117 	goto failure;
118 
119     if (krb5_ret_int16 (sp, &ac->remote_port) != 0)
120 	goto failure;
121     if (flags & SC_KEYBLOCK) {
122 	if (krb5_ret_keyblock (sp, &keyblock) != 0)
123 	    goto failure;
124 	krb5_auth_con_setkey (context, ac, &keyblock);
125 	krb5_free_keyblock_contents (context, &keyblock);
126     }
127     if (flags & SC_LOCAL_SUBKEY) {
128 	if (krb5_ret_keyblock (sp, &keyblock) != 0)
129 	    goto failure;
130 	krb5_auth_con_setlocalsubkey (context, ac, &keyblock);
131 	krb5_free_keyblock_contents (context, &keyblock);
132     }
133     if (flags & SC_REMOTE_SUBKEY) {
134 	if (krb5_ret_keyblock (sp, &keyblock) != 0)
135 	    goto failure;
136 	krb5_auth_con_setremotesubkey (context, ac, &keyblock);
137 	krb5_free_keyblock_contents (context, &keyblock);
138     }
139     if (krb5_ret_uint32 (sp, &ac->local_seqnumber))
140 	goto failure;
141     if (krb5_ret_uint32 (sp, &ac->remote_seqnumber))
142 	goto failure;
143 
144     if (krb5_ret_int32 (sp, &tmp) != 0)
145 	goto failure;
146     ac->keytype = tmp;
147     if (krb5_ret_int32 (sp, &tmp) != 0)
148 	goto failure;
149     ac->cksumtype = tmp;
150 
151     /* names */
152 
153     if (krb5_ret_data (sp, &data))
154 	goto failure;
155     buffer.value  = data.data;
156     buffer.length = data.length;
157 
158     ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
159 				&name);
160     if (ret) {
161 	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID,
162 				    &name);
163 	if (ret) {
164 	    krb5_data_free (&data);
165 	    goto failure;
166 	}
167     }
168     ctx->source = (krb5_principal)name;
169     krb5_data_free (&data);
170 
171     if (krb5_ret_data (sp, &data) != 0)
172 	goto failure;
173     buffer.value  = data.data;
174     buffer.length = data.length;
175 
176     ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
177 				&name);
178     if (ret) {
179 	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID,
180 				    &name);
181 	if (ret) {
182 	    krb5_data_free (&data);
183 	    goto failure;
184 	}
185     }
186     ctx->target = (krb5_principal)name;
187     krb5_data_free (&data);
188 
189     if (krb5_ret_int32 (sp, &tmp))
190 	goto failure;
191     ctx->flags = tmp;
192     if (krb5_ret_int32 (sp, &tmp))
193 	goto failure;
194     ctx->more_flags = tmp;
195     if (krb5_ret_int32 (sp, &tmp))
196 	goto failure;
197     ctx->lifetime = tmp;
198 
199     ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order);
200     if (ret)
201         goto failure;
202 
203     krb5_storage_free (sp);
204 
205     _gsskrb5i_is_cfx(context, ctx, (ctx->more_flags & LOCAL) == 0);
206 
207     *context_handle = (gss_ctx_id_t)ctx;
208 
209     return GSS_S_COMPLETE;
210 
211 failure:
212     krb5_auth_con_free (context,
213 			ctx->auth_context);
214     if (ctx->source != NULL)
215 	krb5_free_principal(context, ctx->source);
216     if (ctx->target != NULL)
217 	krb5_free_principal(context, ctx->target);
218     if (localp)
219 	krb5_free_address (context, localp);
220     if (remotep)
221 	krb5_free_address (context, remotep);
222     if(ctx->order)
223 	_gssapi_msg_order_destroy(&ctx->order);
224     HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
225     krb5_storage_free (sp);
226     free (ctx);
227     *context_handle = GSS_C_NO_CONTEXT;
228     return ret;
229 }
230