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