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"
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(EINVAL, "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
krb5_context context,
110
enum keytype keytype,
111
gss_buffer_set_t *data_set)
113
krb5_keyblock *key = NULL;
114
krb5_storage *sp = NULL;
116
OM_uint32 maj_stat = GSS_S_COMPLETE;
119
krb5_data_zero(&data);
121
sp = krb5_storage_emem();
123
_gsskrb5_clear_status();
128
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
131
ret = _gsskrb5i_get_acceptor_subkey(context_handle, context, &key);
134
ret = _gsskrb5i_get_initiator_subkey(context_handle, context, &key);
137
ret = _gsskrb5i_get_token_key(context_handle, context, &key);
140
_gsskrb5_set_status(EINVAL, "%d is not a valid subkey type", keytype);
144
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
148
_gsskrb5_set_status(EINVAL, "have no subkey of type %d", keytype);
153
ret = krb5_store_keyblock(sp, *key);
154
krb5_free_keyblock (context, key);
158
ret = krb5_storage_to_data(sp, &data);
163
gss_buffer_desc value;
165
value.length = data.length;
166
value.value = data.data;
168
maj_stat = gss_add_buffer_set_member(minor_status,
174
krb5_data_free(&data);
176
krb5_storage_free(sp);
179
maj_stat = GSS_S_FAILURE;
184
static OM_uint32 inquire_sec_context_authz_data
185
(OM_uint32 *minor_status,
186
const gsskrb5_ctx context_handle,
187
krb5_context context,
189
gss_buffer_set_t *data_set)
192
gss_buffer_desc ad_data;
196
*data_set = GSS_C_NO_BUFFER_SET;
198
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
199
if (context_handle->ticket == NULL) {
200
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
201
*minor_status = EINVAL;
202
_gsskrb5_set_status(EINVAL, "No ticket to obtain authz data from");
203
return GSS_S_NO_CONTEXT;
206
ret = krb5_ticket_get_authorization_data_type(context,
207
context_handle->ticket,
210
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
213
return GSS_S_FAILURE;
216
ad_data.value = data.data;
217
ad_data.length = data.length;
219
ret = gss_add_buffer_set_member(minor_status,
223
krb5_data_free(&data);
228
static OM_uint32 inquire_sec_context_has_updated_spnego
229
(OM_uint32 *minor_status,
230
const gsskrb5_ctx context_handle,
231
gss_buffer_set_t *data_set)
236
*data_set = GSS_C_NO_BUFFER_SET;
239
* For Windows SPNEGO implementations, both the initiator and the
240
* acceptor are assumed to have been updated if a "newer" [CLAR] or
241
* different enctype is negotiated for use by the Kerberos GSS-API
244
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
245
_gsskrb5i_is_cfx(context_handle, &is_updated);
246
if (is_updated == 0) {
247
krb5_keyblock *acceptor_subkey;
249
if (context_handle->more_flags & LOCAL)
250
acceptor_subkey = context_handle->auth_context->remote_subkey;
252
acceptor_subkey = context_handle->auth_context->local_subkey;
254
if (acceptor_subkey != NULL)
255
is_updated = (acceptor_subkey->keytype !=
256
context_handle->auth_context->keyblock->keytype);
258
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
260
return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE;
268
export_lucid_sec_context_v1(OM_uint32 *minor_status,
269
gsskrb5_ctx context_handle,
270
krb5_context context,
271
gss_buffer_set_t *data_set)
273
krb5_storage *sp = NULL;
274
OM_uint32 major_status = GSS_S_COMPLETE;
276
krb5_keyblock *key = NULL;
283
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
285
_gsskrb5i_is_cfx(context_handle, &is_cfx);
287
sp = krb5_storage_emem();
289
_gsskrb5_clear_status();
294
ret = krb5_store_int32(sp, 1);
296
ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0);
298
ret = krb5_store_int32(sp, context_handle->lifetime);
300
krb5_auth_con_getlocalseqnumber (context,
301
context_handle->auth_context,
303
ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
305
ret = krb5_store_uint32(sp, (uint32_t)number);
307
krb5_auth_getremoteseqnumber (context,
308
context_handle->auth_context,
310
ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
312
ret = krb5_store_uint32(sp, (uint32_t)number);
314
ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0);
317
ret = _gsskrb5i_get_token_key(context_handle, context, &key);
321
int sign_alg, seal_alg;
323
switch (key->keytype) {
324
case ETYPE_DES_CBC_CRC:
325
case ETYPE_DES_CBC_MD4:
326
case ETYPE_DES_CBC_MD5:
330
case ETYPE_DES3_CBC_MD5:
331
case ETYPE_DES3_CBC_SHA1:
335
case ETYPE_ARCFOUR_HMAC_MD5:
336
case ETYPE_ARCFOUR_HMAC_MD5_56:
345
ret = krb5_store_int32(sp, sign_alg);
347
ret = krb5_store_int32(sp, seal_alg);
350
ret = krb5_store_keyblock(sp, *key);
353
int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0;
355
/* have_acceptor_subkey */
356
ret = krb5_store_int32(sp, subkey_p);
359
ret = krb5_store_keyblock(sp, *key);
361
/* acceptor_subkey */
363
ret = krb5_store_keyblock(sp, *key);
367
ret = krb5_storage_to_data(sp, &data);
371
gss_buffer_desc ad_data;
373
ad_data.value = data.data;
374
ad_data.length = data.length;
376
ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set);
377
krb5_data_free(&data);
384
krb5_free_keyblock (context, key);
386
krb5_storage_free(sp);
389
major_status = GSS_S_FAILURE;
391
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
396
get_authtime(OM_uint32 *minor_status,
398
gss_buffer_set_t *data_set)
401
gss_buffer_desc value;
402
unsigned char buf[4];
405
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
406
if (ctx->ticket == NULL) {
407
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
408
_gsskrb5_set_status(EINVAL, "No ticket to obtain auth time from");
409
*minor_status = EINVAL;
410
return GSS_S_FAILURE;
413
authtime = ctx->ticket->ticket.authtime;
415
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
417
_gsskrb5_encode_om_uint32(authtime, buf);
418
value.length = sizeof(buf);
421
return gss_add_buffer_set_member(minor_status,
429
(OM_uint32 *minor_status,
431
gss_buffer_set_t *data_set)
433
krb5_storage *sp = NULL;
435
OM_uint32 maj_stat = GSS_S_COMPLETE;
436
krb5_error_code ret = EINVAL;
438
sp = krb5_storage_emem();
440
_gsskrb5_clear_status();
441
*minor_status = ENOMEM;
442
return GSS_S_FAILURE;
445
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
446
if (ctx->service_keyblock == NULL) {
447
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
448
_gsskrb5_set_status(EINVAL, "No service keyblock on gssapi context");
449
*minor_status = EINVAL;
450
return GSS_S_FAILURE;
453
krb5_data_zero(&data);
455
ret = krb5_store_keyblock(sp, *ctx->service_keyblock);
457
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
462
ret = krb5_storage_to_data(sp, &data);
467
gss_buffer_desc value;
469
value.length = data.length;
470
value.value = data.data;
472
maj_stat = gss_add_buffer_set_member(minor_status,
478
krb5_data_free(&data);
480
krb5_storage_free(sp);
483
maj_stat = GSS_S_FAILURE;
491
OM_uint32 _gsskrb5_inquire_sec_context_by_oid
492
(OM_uint32 *minor_status,
493
const gss_ctx_id_t context_handle,
494
const gss_OID desired_object,
495
gss_buffer_set_t *data_set)
497
krb5_context context;
498
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
502
*minor_status = EINVAL;
503
return GSS_S_NO_CONTEXT;
506
GSSAPI_KRB5_INIT (&context);
508
if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) {
509
return inquire_sec_context_tkt_flags(minor_status,
512
} else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) {
513
return inquire_sec_context_has_updated_spnego(minor_status,
516
} else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) {
517
return inquire_sec_context_get_subkey(minor_status,
522
} else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) {
523
return inquire_sec_context_get_subkey(minor_status,
528
} else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) {
529
return inquire_sec_context_get_subkey(minor_status,
534
} else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) {
535
return get_authtime(minor_status, ctx, data_set);
536
} else if (oid_prefix_equal(desired_object,
537
GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X,
539
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,
553
return GSS_S_FAILURE;
554
} else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) {
555
return get_service_keyblock(minor_status, ctx, data_set);
558
return GSS_S_FAILURE;