2 * Copyright (c) 2004, PADL Software Pty Ltd.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of PADL Software nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include "krb5/gsskrb5_locl.h"
35 RCSID("$Id: inquire_sec_context_by_oid.c,v 1.11 2006/11/07 14:34:35 lha Exp $");
38 oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix)
46 ret = der_get_oid(oid_enc->elements, oid_enc->length,
52 ret = der_get_oid(prefix_enc->elements, prefix_enc->length,
61 if (oid.length - 1 == prefix.length) {
62 *suffix = oid.components[oid.length - 1];
64 ret = (der_heim_oid_cmp(&oid, &prefix) == 0);
69 der_free_oid(&prefix);
74 static OM_uint32 inquire_sec_context_tkt_flags
75 (OM_uint32 *minor_status,
76 const gsskrb5_ctx context_handle,
77 gss_buffer_set_t *data_set)
81 gss_buffer_desc value;
83 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
85 if (context_handle->ticket == NULL) {
86 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
87 _gsskrb5_set_status("No ticket from which to obtain flags");
88 *minor_status = EINVAL;
89 return GSS_S_BAD_MECH;
92 tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags);
93 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
95 _gsskrb5_encode_om_uint32(tkt_flags, buf);
96 value.length = sizeof(buf);
99 return gss_add_buffer_set_member(minor_status,
104 enum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY };
106 static OM_uint32 inquire_sec_context_get_subkey
107 (OM_uint32 *minor_status,
108 const gsskrb5_ctx context_handle,
109 enum keytype keytype,
110 gss_buffer_set_t *data_set)
112 krb5_keyblock *key = NULL;
113 krb5_storage *sp = NULL;
115 OM_uint32 maj_stat = GSS_S_COMPLETE;
118 krb5_data_zero(&data);
120 sp = krb5_storage_emem();
122 _gsskrb5_clear_status();
127 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
130 ret = _gsskrb5i_get_acceptor_subkey(context_handle, &key);
132 _gsskrb5_set_error_string ();
135 ret = _gsskrb5i_get_initiator_subkey(context_handle, &key);
137 _gsskrb5_set_error_string ();
140 ret = _gsskrb5i_get_token_key(context_handle, &key);
142 _gsskrb5_set_error_string ();
145 _gsskrb5_set_status("%d is not a valid subkey type", keytype);
149 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
153 _gsskrb5_set_status("have no subkey of type %d", keytype);
158 ret = krb5_store_keyblock(sp, *key);
159 krb5_free_keyblock (_gsskrb5_context, key);
161 _gsskrb5_set_error_string ();
165 ret = krb5_storage_to_data(sp, &data);
167 _gsskrb5_set_error_string ();
172 gss_buffer_desc value;
174 value.length = data.length;
175 value.value = data.data;
177 maj_stat = gss_add_buffer_set_member(minor_status,
183 krb5_data_free(&data);
185 krb5_storage_free(sp);
188 maj_stat = GSS_S_FAILURE;
193 static OM_uint32 inquire_sec_context_authz_data
194 (OM_uint32 *minor_status,
195 const gsskrb5_ctx context_handle,
197 gss_buffer_set_t *data_set)
200 gss_buffer_desc ad_data;
204 *data_set = GSS_C_NO_BUFFER_SET;
206 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
207 if (context_handle->ticket == NULL) {
208 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
209 *minor_status = EINVAL;
210 _gsskrb5_set_status("No ticket to obtain authz data from");
211 return GSS_S_NO_CONTEXT;
214 ret = krb5_ticket_get_authorization_data_type(_gsskrb5_context,
215 context_handle->ticket,
218 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
220 _gsskrb5_set_error_string ();
222 return GSS_S_FAILURE;
225 ad_data.value = data.data;
226 ad_data.length = data.length;
228 ret = gss_add_buffer_set_member(minor_status,
232 krb5_data_free(&data);
237 static OM_uint32 inquire_sec_context_has_updated_spnego
238 (OM_uint32 *minor_status,
239 const gsskrb5_ctx context_handle,
240 gss_buffer_set_t *data_set)
245 *data_set = GSS_C_NO_BUFFER_SET;
248 * For Windows SPNEGO implementations, both the initiator and the
249 * acceptor are assumed to have been updated if a "newer" [CLAR] or
250 * different enctype is negotiated for use by the Kerberos GSS-API
253 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
254 _gsskrb5i_is_cfx(context_handle, &is_updated);
255 if (is_updated == 0) {
256 krb5_keyblock *acceptor_subkey;
258 if (context_handle->more_flags & LOCAL)
259 acceptor_subkey = context_handle->auth_context->remote_subkey;
261 acceptor_subkey = context_handle->auth_context->local_subkey;
263 if (acceptor_subkey != NULL)
264 is_updated = (acceptor_subkey->keytype !=
265 context_handle->auth_context->keyblock->keytype);
267 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
269 return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE;
277 export_lucid_sec_context_v1(OM_uint32 *minor_status,
278 gsskrb5_ctx context_handle,
279 gss_buffer_set_t *data_set)
281 krb5_storage *sp = NULL;
282 OM_uint32 major_status = GSS_S_COMPLETE;
284 krb5_keyblock *key = NULL;
293 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
295 _gsskrb5i_is_cfx(context_handle, &is_cfx);
297 sp = krb5_storage_emem();
299 _gsskrb5_clear_status();
304 ret = krb5_store_int32(sp, 1);
306 ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0);
308 ret = krb5_store_int32(sp, context_handle->lifetime);
310 krb5_auth_con_getlocalseqnumber (_gsskrb5_context,
311 context_handle->auth_context,
313 ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
314 ret = krb5_store_uint32(sp, (uint32_t)number);
315 krb5_auth_getremoteseqnumber (_gsskrb5_context,
316 context_handle->auth_context,
318 ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
319 ret = krb5_store_uint32(sp, (uint32_t)number);
320 ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0);
323 ret = _gsskrb5i_get_token_key(context_handle, &key);
327 int sign_alg, seal_alg;
329 switch (key->keytype) {
330 case ETYPE_DES_CBC_CRC:
331 case ETYPE_DES_CBC_MD4:
332 case ETYPE_DES_CBC_MD5:
336 case ETYPE_DES3_CBC_MD5:
337 case ETYPE_DES3_CBC_SHA1:
341 case ETYPE_ARCFOUR_HMAC_MD5:
342 case ETYPE_ARCFOUR_HMAC_MD5_56:
351 ret = krb5_store_int32(sp, sign_alg);
353 ret = krb5_store_int32(sp, seal_alg);
356 ret = krb5_store_keyblock(sp, *key);
359 int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0;
361 /* have_acceptor_subkey */
362 ret = krb5_store_int32(sp, subkey_p);
365 ret = krb5_store_keyblock(sp, *key);
367 /* acceptor_subkey */
369 ret = krb5_store_keyblock(sp, *key);
373 ret = krb5_storage_to_data(sp, &data);
377 gss_buffer_desc ad_data;
379 ad_data.value = data.data;
380 ad_data.length = data.length;
382 ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set);
383 krb5_data_free(&data);
390 krb5_free_keyblock (_gsskrb5_context, key);
392 krb5_storage_free(sp);
395 major_status = GSS_S_FAILURE;
397 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
402 get_authtime(OM_uint32 *minor_status,
404 gss_buffer_set_t *data_set)
407 gss_buffer_desc value;
408 unsigned char buf[4];
411 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
412 if (ctx->ticket == NULL) {
413 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
414 _gsskrb5_set_status("No ticket to obtain auth time from");
415 *minor_status = EINVAL;
416 return GSS_S_FAILURE;
419 authtime = ctx->ticket->ticket.authtime;
421 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
423 _gsskrb5_encode_om_uint32(authtime, buf);
424 value.length = sizeof(buf);
427 return gss_add_buffer_set_member(minor_status,
435 (OM_uint32 *minor_status,
437 gss_buffer_set_t *data_set)
439 krb5_storage *sp = NULL;
441 OM_uint32 maj_stat = GSS_S_COMPLETE;
442 krb5_error_code ret = EINVAL;
444 sp = krb5_storage_emem();
446 _gsskrb5_clear_status();
447 *minor_status = ENOMEM;
448 return GSS_S_FAILURE;
451 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
452 if (ctx->service_keyblock == NULL) {
453 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
454 _gsskrb5_set_status("No service keyblock on gssapi context");
455 *minor_status = EINVAL;
456 return GSS_S_FAILURE;
459 krb5_data_zero(&data);
461 ret = krb5_store_keyblock(sp, *ctx->service_keyblock);
463 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
468 ret = krb5_storage_to_data(sp, &data);
473 gss_buffer_desc value;
475 value.length = data.length;
476 value.value = data.data;
478 maj_stat = gss_add_buffer_set_member(minor_status,
484 krb5_data_free(&data);
486 krb5_storage_free(sp);
488 _gsskrb5_set_error_string ();
490 maj_stat = GSS_S_FAILURE;
498 OM_uint32 _gsskrb5_inquire_sec_context_by_oid
499 (OM_uint32 *minor_status,
500 const gss_ctx_id_t context_handle,
501 const gss_OID desired_object,
502 gss_buffer_set_t *data_set)
504 const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
508 *minor_status = EINVAL;
509 return GSS_S_NO_CONTEXT;
512 if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) {
513 return inquire_sec_context_tkt_flags(minor_status,
516 } else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) {
517 return inquire_sec_context_has_updated_spnego(minor_status,
520 } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) {
521 return inquire_sec_context_get_subkey(minor_status,
525 } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) {
526 return inquire_sec_context_get_subkey(minor_status,
530 } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) {
531 return inquire_sec_context_get_subkey(minor_status,
535 } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) {
536 return get_authtime(minor_status, ctx, data_set);
537 } else if (oid_prefix_equal(desired_object,
538 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X,
540 return inquire_sec_context_authz_data(minor_status,
544 } else if (oid_prefix_equal(desired_object,
545 GSS_KRB5_EXPORT_LUCID_CONTEXT_X,
548 return export_lucid_sec_context_v1(minor_status,
552 return GSS_S_FAILURE;
553 } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) {
554 return get_service_keyblock(minor_status, ctx, data_set);
557 return GSS_S_FAILURE;