1 /*
2 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
3 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 */
6 /* -*- mode: c; indent-tabs-mode: nil -*- */
7 /*
8 * Copyright 1993 by OpenVision Technologies, Inc.
9 *
10 * Permission to use, copy, modify, distribute, and sell this software
11 * and its documentation for any purpose is hereby granted without fee,
12 * provided that the above copyright notice appears in all copies and
13 * that both that copyright notice and this permission notice appear in
14 * supporting documentation, and that the name of OpenVision not be used
15 * in advertising or publicity pertaining to distribution of the software
16 * without specific, written prior permission. OpenVision makes no
17 * representations about the suitability of this software for any
18 * purpose. It is provided "as is" without express or implied warranty.
19 *
20 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
22 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 * PERFORMANCE OF THIS SOFTWARE.
27 */
28 /*
29 * Copyright (c) 2006-2008, Novell, Inc.
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions are met:
34 *
35 * * Redistributions of source code must retain the above copyright notice,
36 * this list of conditions and the following disclaimer.
37 * * Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * * The copyright holder's name is not used to endorse or promote products
41 * derived from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
44 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
47 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53 * POSSIBILITY OF SUCH DAMAGE.
54 */
55 /*
56 * Copyright (c) 2006-2008, Novell, Inc.
57 * All rights reserved.
58 *
59 * Redistribution and use in source and binary forms, with or without
60 * modification, are permitted provided that the following conditions are met:
61 *
62 * * Redistributions of source code must retain the above copyright notice,
63 * this list of conditions and the following disclaimer.
64 * * Redistributions in binary form must reproduce the above copyright
65 * notice, this list of conditions and the following disclaimer in the
66 * documentation and/or other materials provided with the distribution.
67 * * The copyright holder's name is not used to endorse or promote products
68 * derived from this software without specific prior written permission.
69 *
70 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
71 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
74 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
75 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
76 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
78 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
79 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
80 * POSSIBILITY OF SUCH DAMAGE.
81 */
82
83 #include "gssapiP_krb5.h"
84 #include "mechglueP.h" /* SUNW17PACresync */
85
86 OM_uint32
krb5_gss_inquire_context(minor_status,context_handle,initiator_name,acceptor_name,lifetime_rec,mech_type,ret_flags,locally_initiated,opened)87 krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
88 acceptor_name, lifetime_rec, mech_type, ret_flags,
89 locally_initiated, opened)
90 OM_uint32 *minor_status;
91 gss_ctx_id_t context_handle;
92 gss_name_t *initiator_name;
93 gss_name_t *acceptor_name;
94 OM_uint32 *lifetime_rec;
95 gss_OID *mech_type;
96 OM_uint32 *ret_flags;
97 int *locally_initiated;
98 int *opened;
99 {
100 krb5_context context;
101 krb5_error_code code;
102 krb5_gss_ctx_id_rec *ctx;
103 krb5_principal initiator, acceptor;
104 krb5_timestamp now;
105 krb5_deltat lifetime;
106
107 if (initiator_name)
108 *initiator_name = (gss_name_t) NULL;
109 if (acceptor_name)
110 *acceptor_name = (gss_name_t) NULL;
111
112 /* validate the context handle */
113 if (! kg_validate_ctx_id(context_handle)) {
114 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
115 return(GSS_S_NO_CONTEXT);
116 }
117
118 ctx = (krb5_gss_ctx_id_rec *) context_handle;
119
120 if (! ctx->established) {
121 *minor_status = KG_CTX_INCOMPLETE;
122 return(GSS_S_NO_CONTEXT);
123 }
124
125 initiator = NULL;
126 acceptor = NULL;
127 context = ctx->k5_context;
128
129 if ((code = krb5_timeofday(context, &now))) {
130 *minor_status = code;
131 save_error_info(*minor_status, context);
132 return(GSS_S_FAILURE);
133 }
134
135
136 /* SUNW17PACresync - should be krb_times.endtime (revisit) */
137 if ((lifetime = ctx->endtime - now) < 0)
138 lifetime = 0;
139
140 if (initiator_name) {
141 if ((code = krb5_copy_principal(context,
142 ctx->initiate?ctx->here:ctx->there,
143 &initiator))) {
144 *minor_status = code;
145 save_error_info(*minor_status, context);
146 return(GSS_S_FAILURE);
147 }
148 if (! kg_save_name((gss_name_t) initiator)) {
149 krb5_free_principal(context, initiator);
150 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
151 return(GSS_S_FAILURE);
152 }
153 }
154
155 if (acceptor_name) {
156 if ((code = krb5_copy_principal(context,
157 ctx->initiate?ctx->there:ctx->here,
158 &acceptor))) {
159 if (initiator) krb5_free_principal(context, initiator);
160 *minor_status = code;
161 save_error_info(*minor_status, context);
162 return(GSS_S_FAILURE);
163 }
164 if (! kg_save_name((gss_name_t) acceptor)) {
165 krb5_free_principal(context, acceptor);
166 if (initiator) {
167 kg_delete_name((gss_name_t) initiator);
168 krb5_free_principal(context, initiator);
169 }
170 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
171 return(GSS_S_FAILURE);
172 }
173 }
174
175 if (initiator_name)
176 *initiator_name = (gss_name_t) initiator;
177
178 if (acceptor_name)
179 *acceptor_name = (gss_name_t) acceptor;
180
181 if (lifetime_rec)
182 *lifetime_rec = lifetime;
183
184 if (mech_type)
185 *mech_type = (gss_OID) ctx->mech_used;
186
187 if (ret_flags)
188 *ret_flags = ctx->gss_flags;
189
190 if (locally_initiated)
191 *locally_initiated = ctx->initiate;
192
193 if (opened)
194 *opened = ctx->established;
195
196 *minor_status = 0;
197
198 return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
199 }
200
201 OM_uint32
gss_krb5int_inq_session_key(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,const gss_OID desired_object,gss_buffer_set_t * data_set)202 gss_krb5int_inq_session_key(
203 OM_uint32 *minor_status,
204 const gss_ctx_id_t context_handle,
205 const gss_OID desired_object,
206 gss_buffer_set_t *data_set)
207 {
208 krb5_gss_ctx_id_rec *ctx;
209 krb5_keyblock *key;
210 gss_buffer_desc keyvalue, keyinfo;
211 OM_uint32 major_status, minor;
212 unsigned char oid_buf[GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH + 6];
213 gss_OID_desc oid;
214
215 ctx = (krb5_gss_ctx_id_rec *) context_handle;
216 key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey;
217
218 keyvalue.value = key->contents;
219 keyvalue.length = key->length;
220
221 major_status = generic_gss_add_buffer_set_member(minor_status, &keyvalue, data_set);
222 if (GSS_ERROR(major_status))
223 goto cleanup;
224
225 oid.elements = oid_buf;
226 oid.length = sizeof(oid_buf);
227
228 major_status = generic_gss_oid_compose(minor_status,
229 GSS_KRB5_SESSION_KEY_ENCTYPE_OID,
230 GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
231 key->enctype,
232 &oid);
233 if (GSS_ERROR(major_status))
234 goto cleanup;
235
236 keyinfo.value = oid.elements;
237 keyinfo.length = oid.length;
238
239 major_status = generic_gss_add_buffer_set_member(minor_status, &keyinfo, data_set);
240 if (GSS_ERROR(major_status))
241 goto cleanup;
242
243 return GSS_S_COMPLETE;
244
245 cleanup:
246 if (*data_set != GSS_C_NO_BUFFER_SET) {
247 if ((*data_set)->count != 0)
248 memset((*data_set)->elements[0].value, 0, (*data_set)->elements[0].length);
249 gss_release_buffer_set(&minor, data_set);
250 }
251
252 return major_status;
253 }
254
255 OM_uint32
gss_krb5int_extract_authz_data_from_sec_context(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,const gss_OID desired_object,gss_buffer_set_t * data_set)256 gss_krb5int_extract_authz_data_from_sec_context(
257 OM_uint32 *minor_status,
258 const gss_ctx_id_t context_handle,
259 const gss_OID desired_object,
260 gss_buffer_set_t *data_set)
261 {
262 gss_buffer_desc ad_data;
263 OM_uint32 major_status;
264 krb5_error_code code;
265 krb5_gss_ctx_id_rec *ctx;
266 int ad_type = 0;
267 int i, j;
268
269 *data_set = GSS_C_NO_BUFFER_SET;
270
271 ctx = (krb5_gss_ctx_id_rec *) context_handle;
272
273 major_status = generic_gss_oid_decompose(minor_status,
274 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID,
275 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH,
276 desired_object,
277 &ad_type);
278 if (major_status != GSS_S_COMPLETE || ad_type == 0) {
279 *minor_status = ENOENT;
280 return major_status; /* SUNW17PACresync */
281 }
282
283 if (ctx->authdata != NULL) {
284 for (i = 0; ctx->authdata[i] != NULL; i++) {
285 if (ctx->authdata[i]->ad_type == ad_type) {
286
287 ad_data.length = ctx->authdata[i]->length;
288 ad_data.value = ctx->authdata[i]->contents;
289
290 major_status = generic_gss_add_buffer_set_member(minor_status,
291 &ad_data, data_set);
292 if (GSS_ERROR(major_status))
293 break;
294 } else if (ctx->authdata[i]->ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
295 /*
296 * Solaris Kerberos (illumos)
297 * Unwrap the AD-IF-RELEVANT object and look inside.
298 */
299 krb5_authdata **ad_if_relevant = NULL;
300 code = krb5_decode_authdata_container(ctx->k5_context,
301 KRB5_AUTHDATA_IF_RELEVANT,
302 ctx->authdata[i],
303 &ad_if_relevant);
304 if (code != 0)
305 continue;
306
307 for (j = 0; ad_if_relevant[j] != NULL; j++) {
308 if (ad_if_relevant[j]->ad_type == ad_type) {
309 ad_data.length = ad_if_relevant[j]->length;
310 ad_data.value = ad_if_relevant[j]->contents;
311
312 major_status = generic_gss_add_buffer_set_member(minor_status,
313 &ad_data, data_set);
314 if (GSS_ERROR(major_status)) {
315 krb5_free_authdata(ctx->k5_context, ad_if_relevant);
316 goto break2;
317 }
318 }
319 }
320 krb5_free_authdata(ctx->k5_context, ad_if_relevant);
321 /* Solaris Kerberos (illumos) */
322 }
323 }
324 }
325
326 break2:
327 if (GSS_ERROR(major_status)) {
328 OM_uint32 tmp;
329
330 generic_gss_release_buffer_set(&tmp, data_set);
331 }
332
333 return major_status;
334 }
335
336 OM_uint32
gss_krb5int_extract_authtime_from_sec_context(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,const gss_OID desired_oid,gss_buffer_set_t * data_set)337 gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status,
338 const gss_ctx_id_t context_handle,
339 const gss_OID desired_oid,
340 gss_buffer_set_t *data_set)
341 {
342 krb5_gss_ctx_id_rec *ctx;
343 gss_buffer_desc rep;
344
345 ctx = (krb5_gss_ctx_id_rec *) context_handle;
346
347 rep.value = &ctx->krb_times.authtime;
348 rep.length = sizeof(ctx->krb_times.authtime);
349
350 return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
351 }
352
353