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 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 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 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 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