inquire_sec_context_by_oid.c revision 256281
1230557Sjimharris/*
2230557Sjimharris * Copyright (c) 2004, PADL Software Pty Ltd.
3230557Sjimharris * All rights reserved.
4230557Sjimharris *
5230557Sjimharris * Redistribution and use in source and binary forms, with or without
6230557Sjimharris * modification, are permitted provided that the following conditions
7230557Sjimharris * are met:
8230557Sjimharris *
9230557Sjimharris * 1. Redistributions of source code must retain the above copyright
10230557Sjimharris *    notice, this list of conditions and the following disclaimer.
11230557Sjimharris *
12230557Sjimharris * 2. Redistributions in binary form must reproduce the above copyright
13230557Sjimharris *    notice, this list of conditions and the following disclaimer in the
14230557Sjimharris *    documentation and/or other materials provided with the distribution.
15230557Sjimharris *
16230557Sjimharris * 3. Neither the name of PADL Software nor the names of its contributors
17230557Sjimharris *    may be used to endorse or promote products derived from this software
18230557Sjimharris *    without specific prior written permission.
19230557Sjimharris *
20230557Sjimharris * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21230557Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22230557Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23230557Sjimharris * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24230557Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25230557Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26230557Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27230557Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28230557Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29230557Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30230557Sjimharris * SUCH DAMAGE.
31230557Sjimharris */
32230557Sjimharris
33230557Sjimharris#include "gsskrb5_locl.h"
34230557Sjimharris
35230557Sjimharrisstatic int
36230557Sjimharrisoid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix)
37230557Sjimharris{
38230557Sjimharris    int ret;
39230557Sjimharris    heim_oid oid;
40230557Sjimharris    heim_oid prefix;
41230557Sjimharris
42230557Sjimharris    *suffix = 0;
43230557Sjimharris
44230557Sjimharris    ret = der_get_oid(oid_enc->elements, oid_enc->length,
45230557Sjimharris		      &oid, NULL);
46230557Sjimharris    if (ret) {
47230557Sjimharris	return 0;
48230557Sjimharris    }
49230557Sjimharris
50230557Sjimharris    ret = der_get_oid(prefix_enc->elements, prefix_enc->length,
51230557Sjimharris		      &prefix, NULL);
52230557Sjimharris    if (ret) {
53230557Sjimharris	der_free_oid(&oid);
54230557Sjimharris	return 0;
55230557Sjimharris    }
56230557Sjimharris
57230557Sjimharris    ret = 0;
58230557Sjimharris
59230557Sjimharris    if (oid.length - 1 == prefix.length) {
60230557Sjimharris	*suffix = oid.components[oid.length - 1];
61230557Sjimharris	oid.length--;
62230557Sjimharris	ret = (der_heim_oid_cmp(&oid, &prefix) == 0);
63230557Sjimharris	oid.length++;
64230557Sjimharris    }
65230557Sjimharris
66230557Sjimharris    der_free_oid(&oid);
67230557Sjimharris    der_free_oid(&prefix);
68230557Sjimharris
69230557Sjimharris    return ret;
70230557Sjimharris}
71230557Sjimharris
72230557Sjimharrisstatic OM_uint32 inquire_sec_context_tkt_flags
73230557Sjimharris           (OM_uint32 *minor_status,
74230557Sjimharris            const gsskrb5_ctx context_handle,
75230557Sjimharris            gss_buffer_set_t *data_set)
76230557Sjimharris{
77230557Sjimharris    OM_uint32 tkt_flags;
78230557Sjimharris    unsigned char buf[4];
79230557Sjimharris    gss_buffer_desc value;
80230557Sjimharris
81230557Sjimharris    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
82230557Sjimharris
83230557Sjimharris    if (context_handle->ticket == NULL) {
84230557Sjimharris	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
85230557Sjimharris	_gsskrb5_set_status(EINVAL, "No ticket from which to obtain flags");
86230557Sjimharris	*minor_status = EINVAL;
87230557Sjimharris	return GSS_S_BAD_MECH;
88230557Sjimharris    }
89230557Sjimharris
90230557Sjimharris    tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags);
91230557Sjimharris    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
92230557Sjimharris
93230557Sjimharris    _gsskrb5_encode_om_uint32(tkt_flags, buf);
94230557Sjimharris    value.length = sizeof(buf);
95230557Sjimharris    value.value = buf;
96230557Sjimharris
97230557Sjimharris    return gss_add_buffer_set_member(minor_status,
98230557Sjimharris				     &value,
99230557Sjimharris				     data_set);
100230557Sjimharris}
101230557Sjimharris
102230557Sjimharrisenum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY };
103230557Sjimharris
104230557Sjimharrisstatic OM_uint32 inquire_sec_context_get_subkey
105230557Sjimharris           (OM_uint32 *minor_status,
106230557Sjimharris            const gsskrb5_ctx context_handle,
107230557Sjimharris	    krb5_context context,
108230557Sjimharris	    enum keytype keytype,
109230557Sjimharris            gss_buffer_set_t *data_set)
110230557Sjimharris{
111230557Sjimharris    krb5_keyblock *key = NULL;
112230557Sjimharris    krb5_storage *sp = NULL;
113230557Sjimharris    krb5_data data;
114230557Sjimharris    OM_uint32 maj_stat = GSS_S_COMPLETE;
115230557Sjimharris    krb5_error_code ret;
116230557Sjimharris
117230557Sjimharris    krb5_data_zero(&data);
118230557Sjimharris
119230557Sjimharris    sp = krb5_storage_emem();
120230557Sjimharris    if (sp == NULL) {
121230557Sjimharris	_gsskrb5_clear_status();
122230557Sjimharris	ret = ENOMEM;
123230557Sjimharris	goto out;
124230557Sjimharris    }
125230557Sjimharris
126230557Sjimharris    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
127230557Sjimharris    switch(keytype) {
128230557Sjimharris    case ACCEPTOR_KEY:
129230557Sjimharris	ret = _gsskrb5i_get_acceptor_subkey(context_handle, context, &key);
130230557Sjimharris	break;
131230557Sjimharris    case INITIATOR_KEY:
132230557Sjimharris	ret = _gsskrb5i_get_initiator_subkey(context_handle, context, &key);
133230557Sjimharris	break;
134230557Sjimharris    case TOKEN_KEY:
135230557Sjimharris	ret = _gsskrb5i_get_token_key(context_handle, context, &key);
136230557Sjimharris	break;
137230557Sjimharris    default:
138230557Sjimharris	_gsskrb5_set_status(EINVAL, "%d is not a valid subkey type", keytype);
139230557Sjimharris	ret = EINVAL;
140230557Sjimharris	break;
141230557Sjimharris   }
142230557Sjimharris    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
143230557Sjimharris    if (ret)
144230557Sjimharris	goto out;
145230557Sjimharris    if (key == NULL) {
146230557Sjimharris	_gsskrb5_set_status(EINVAL, "have no subkey of type %d", keytype);
147230557Sjimharris	ret = EINVAL;
148230557Sjimharris	goto out;
149230557Sjimharris    }
150230557Sjimharris
151230557Sjimharris    ret = krb5_store_keyblock(sp, *key);
152230557Sjimharris    krb5_free_keyblock (context, key);
153230557Sjimharris    if (ret)
154230557Sjimharris	goto out;
155230557Sjimharris
156230557Sjimharris    ret = krb5_storage_to_data(sp, &data);
157230557Sjimharris    if (ret)
158230557Sjimharris	goto out;
159230557Sjimharris
160230557Sjimharris    {
161230557Sjimharris	gss_buffer_desc value;
162230557Sjimharris
163230557Sjimharris	value.length = data.length;
164230557Sjimharris	value.value = data.data;
165230557Sjimharris
166230557Sjimharris	maj_stat = gss_add_buffer_set_member(minor_status,
167230557Sjimharris					     &value,
168230557Sjimharris					     data_set);
169230557Sjimharris    }
170230557Sjimharris
171230557Sjimharrisout:
172230557Sjimharris    krb5_data_free(&data);
173230557Sjimharris    if (sp)
174230557Sjimharris	krb5_storage_free(sp);
175230557Sjimharris    if (ret) {
176230557Sjimharris	*minor_status = ret;
177230557Sjimharris	maj_stat = GSS_S_FAILURE;
178230557Sjimharris    }
179230557Sjimharris    return maj_stat;
180230557Sjimharris}
181230557Sjimharris
182230557Sjimharrisstatic OM_uint32 inquire_sec_context_get_sspi_session_key
183230557Sjimharris            (OM_uint32 *minor_status,
184230557Sjimharris             const gsskrb5_ctx context_handle,
185230557Sjimharris             krb5_context context,
186230557Sjimharris             gss_buffer_set_t *data_set)
187230557Sjimharris{
188230557Sjimharris    krb5_keyblock *key;
189230557Sjimharris    OM_uint32 maj_stat = GSS_S_COMPLETE;
190230557Sjimharris    krb5_error_code ret;
191230557Sjimharris    gss_buffer_desc value;
192230557Sjimharris
193230557Sjimharris    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
194230557Sjimharris    ret = _gsskrb5i_get_token_key(context_handle, context, &key);
195230557Sjimharris    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
196230557Sjimharris
197230557Sjimharris    if (ret)
198230557Sjimharris        goto out;
199230557Sjimharris    if (key == NULL) {
200230557Sjimharris        ret = EINVAL;
201230557Sjimharris        goto out;
202230557Sjimharris    }
203230557Sjimharris
204230557Sjimharris    value.length = key->keyvalue.length;
205230557Sjimharris    value.value = key->keyvalue.data;
206230557Sjimharris
207230557Sjimharris    maj_stat = gss_add_buffer_set_member(minor_status,
208230557Sjimharris                                         &value,
209230557Sjimharris                                         data_set);
210230557Sjimharris    krb5_free_keyblock(context, key);
211230557Sjimharris
212230557Sjimharris    /* MIT also returns the enctype encoded as an OID in data_set[1] */
213230557Sjimharris
214230557Sjimharrisout:
215230557Sjimharris    if (ret) {
216230557Sjimharris        *minor_status = ret;
217230557Sjimharris        maj_stat = GSS_S_FAILURE;
218230557Sjimharris    }
219230557Sjimharris    return maj_stat;
220230557Sjimharris}
221230557Sjimharris
222230557Sjimharrisstatic OM_uint32 inquire_sec_context_authz_data
223230557Sjimharris           (OM_uint32 *minor_status,
224230557Sjimharris            const gsskrb5_ctx context_handle,
225230557Sjimharris	    krb5_context context,
226230557Sjimharris            unsigned ad_type,
227230557Sjimharris            gss_buffer_set_t *data_set)
228230557Sjimharris{
229230557Sjimharris    krb5_data data;
230230557Sjimharris    gss_buffer_desc ad_data;
231230557Sjimharris    OM_uint32 ret;
232230557Sjimharris
233230557Sjimharris    *minor_status = 0;
234230557Sjimharris    *data_set = GSS_C_NO_BUFFER_SET;
235230557Sjimharris
236230557Sjimharris    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
237230557Sjimharris    if (context_handle->ticket == NULL) {
238230557Sjimharris	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
239230557Sjimharris	*minor_status = EINVAL;
240230557Sjimharris	_gsskrb5_set_status(EINVAL, "No ticket to obtain authz data from");
241230557Sjimharris	return GSS_S_NO_CONTEXT;
242230557Sjimharris    }
243230557Sjimharris
244230557Sjimharris    ret = krb5_ticket_get_authorization_data_type(context,
245230557Sjimharris						  context_handle->ticket,
246230557Sjimharris						  ad_type,
247230557Sjimharris						  &data);
248230557Sjimharris    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
249230557Sjimharris    if (ret) {
250230557Sjimharris	*minor_status = ret;
251230557Sjimharris	return GSS_S_FAILURE;
252230557Sjimharris    }
253230557Sjimharris
254230557Sjimharris    ad_data.value = data.data;
255230557Sjimharris    ad_data.length = data.length;
256230557Sjimharris
257230557Sjimharris    ret = gss_add_buffer_set_member(minor_status,
258230557Sjimharris				    &ad_data,
259230557Sjimharris				    data_set);
260230557Sjimharris
261230557Sjimharris    krb5_data_free(&data);
262230557Sjimharris
263230557Sjimharris    return ret;
264230557Sjimharris}
265230557Sjimharris
266230557Sjimharrisstatic OM_uint32 inquire_sec_context_has_updated_spnego
267230557Sjimharris           (OM_uint32 *minor_status,
268230557Sjimharris            const gsskrb5_ctx context_handle,
269230557Sjimharris            gss_buffer_set_t *data_set)
270230557Sjimharris{
271230557Sjimharris    int is_updated = 0;
272230557Sjimharris
273230557Sjimharris    *minor_status = 0;
274230557Sjimharris    *data_set = GSS_C_NO_BUFFER_SET;
275230557Sjimharris
276230557Sjimharris    /*
277230557Sjimharris     * For Windows SPNEGO implementations, both the initiator and the
278230557Sjimharris     * acceptor are assumed to have been updated if a "newer" [CLAR] or
279230557Sjimharris     * different enctype is negotiated for use by the Kerberos GSS-API
280230557Sjimharris     * mechanism.
281230557Sjimharris     */
282230557Sjimharris    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
283230557Sjimharris    is_updated = (context_handle->more_flags & IS_CFX);
284230557Sjimharris    if (is_updated == 0) {
285230557Sjimharris	krb5_keyblock *acceptor_subkey;
286230557Sjimharris
287230557Sjimharris	if (context_handle->more_flags & LOCAL)
288230557Sjimharris	    acceptor_subkey = context_handle->auth_context->remote_subkey;
289230557Sjimharris	else
290230557Sjimharris	    acceptor_subkey = context_handle->auth_context->local_subkey;
291230557Sjimharris
292230557Sjimharris	if (acceptor_subkey != NULL)
293230557Sjimharris	    is_updated = (acceptor_subkey->keytype !=
294230557Sjimharris			  context_handle->auth_context->keyblock->keytype);
295230557Sjimharris    }
296230557Sjimharris    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
297230557Sjimharris
298230557Sjimharris    return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE;
299230557Sjimharris}
300230557Sjimharris
301230557Sjimharris/*
302230557Sjimharris *
303230557Sjimharris */
304230557Sjimharris
305230557Sjimharrisstatic OM_uint32
306230557Sjimharrisexport_lucid_sec_context_v1(OM_uint32 *minor_status,
307230557Sjimharris			    gsskrb5_ctx context_handle,
308230557Sjimharris			    krb5_context context,
309230557Sjimharris			    gss_buffer_set_t *data_set)
310230557Sjimharris{
311230557Sjimharris    krb5_storage *sp = NULL;
312230557Sjimharris    OM_uint32 major_status = GSS_S_COMPLETE;
313230557Sjimharris    krb5_error_code ret;
314230557Sjimharris    krb5_keyblock *key = NULL;
315230557Sjimharris    int32_t number;
316230557Sjimharris    int is_cfx;
317230557Sjimharris    krb5_data data;
318230557Sjimharris
319230557Sjimharris    *minor_status = 0;
320230557Sjimharris
321230557Sjimharris    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
322230557Sjimharris
323230557Sjimharris    is_cfx = (context_handle->more_flags & IS_CFX);
324230557Sjimharris
325230557Sjimharris    sp = krb5_storage_emem();
326230557Sjimharris    if (sp == NULL) {
327230557Sjimharris	_gsskrb5_clear_status();
328230557Sjimharris	ret = ENOMEM;
329230557Sjimharris	goto out;
330230557Sjimharris    }
331230557Sjimharris
332230557Sjimharris    ret = krb5_store_int32(sp, 1);
333230557Sjimharris    if (ret) goto out;
334230557Sjimharris    ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0);
335230557Sjimharris    if (ret) goto out;
336230557Sjimharris    ret = krb5_store_int32(sp, context_handle->lifetime);
337230557Sjimharris    if (ret) goto out;
338230557Sjimharris    krb5_auth_con_getlocalseqnumber (context,
339230557Sjimharris				     context_handle->auth_context,
340230557Sjimharris				     &number);
341230557Sjimharris    ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
342230557Sjimharris    if (ret) goto out;
343230557Sjimharris    ret = krb5_store_uint32(sp, (uint32_t)number);
344230557Sjimharris    if (ret) goto out;
345230557Sjimharris    krb5_auth_con_getremoteseqnumber (context,
346230557Sjimharris				      context_handle->auth_context,
347230557Sjimharris				      &number);
348230557Sjimharris    ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
349230557Sjimharris    if (ret) goto out;
350230557Sjimharris    ret = krb5_store_uint32(sp, (uint32_t)number);
351230557Sjimharris    if (ret) goto out;
352230557Sjimharris    ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0);
353230557Sjimharris    if (ret) goto out;
354230557Sjimharris
355230557Sjimharris    ret = _gsskrb5i_get_token_key(context_handle, context, &key);
356230557Sjimharris    if (ret) goto out;
357230557Sjimharris
358230557Sjimharris    if (is_cfx == 0) {
359230557Sjimharris	int sign_alg, seal_alg;
360230557Sjimharris
361230557Sjimharris	switch (key->keytype) {
362230557Sjimharris	case ETYPE_DES_CBC_CRC:
363230557Sjimharris	case ETYPE_DES_CBC_MD4:
364230557Sjimharris	case ETYPE_DES_CBC_MD5:
365230557Sjimharris	    sign_alg = 0;
366230557Sjimharris	    seal_alg = 0;
367230557Sjimharris	    break;
368230557Sjimharris	case ETYPE_DES3_CBC_MD5:
369230557Sjimharris	case ETYPE_DES3_CBC_SHA1:
370230557Sjimharris	    sign_alg = 4;
371230557Sjimharris	    seal_alg = 2;
372230557Sjimharris	    break;
373230557Sjimharris	case ETYPE_ARCFOUR_HMAC_MD5:
374230557Sjimharris	case ETYPE_ARCFOUR_HMAC_MD5_56:
375230557Sjimharris	    sign_alg = 17;
376230557Sjimharris	    seal_alg = 16;
377230557Sjimharris	    break;
378230557Sjimharris	default:
379230557Sjimharris	    sign_alg = -1;
380230557Sjimharris	    seal_alg = -1;
381230557Sjimharris	    break;
382230557Sjimharris	}
383230557Sjimharris	ret = krb5_store_int32(sp, sign_alg);
384230557Sjimharris	if (ret) goto out;
385230557Sjimharris	ret = krb5_store_int32(sp, seal_alg);
386230557Sjimharris	if (ret) goto out;
387230557Sjimharris	/* ctx_key */
388230557Sjimharris	ret = krb5_store_keyblock(sp, *key);
389230557Sjimharris	if (ret) goto out;
390230557Sjimharris    } else {
391230557Sjimharris	int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0;
392230557Sjimharris
393230557Sjimharris	/* have_acceptor_subkey */
394230557Sjimharris	ret = krb5_store_int32(sp, subkey_p);
395230557Sjimharris	if (ret) goto out;
396230557Sjimharris	/* ctx_key */
397230557Sjimharris	ret = krb5_store_keyblock(sp, *key);
398230557Sjimharris	if (ret) goto out;
399230557Sjimharris	/* acceptor_subkey */
400230557Sjimharris	if (subkey_p) {
401230557Sjimharris	    ret = krb5_store_keyblock(sp, *key);
402230557Sjimharris	    if (ret) goto out;
403230557Sjimharris	}
404230557Sjimharris    }
405230557Sjimharris    ret = krb5_storage_to_data(sp, &data);
406230557Sjimharris    if (ret) goto out;
407230557Sjimharris
408230557Sjimharris    {
409230557Sjimharris	gss_buffer_desc ad_data;
410230557Sjimharris
411230557Sjimharris	ad_data.value = data.data;
412230557Sjimharris	ad_data.length = data.length;
413230557Sjimharris
414230557Sjimharris	ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set);
415230557Sjimharris	krb5_data_free(&data);
416230557Sjimharris	if (ret)
417230557Sjimharris	    goto out;
418230557Sjimharris    }
419230557Sjimharris
420230557Sjimharrisout:
421230557Sjimharris    if (key)
422230557Sjimharris	krb5_free_keyblock (context, key);
423230557Sjimharris    if (sp)
424230557Sjimharris	krb5_storage_free(sp);
425230557Sjimharris    if (ret) {
426230557Sjimharris	*minor_status = ret;
427230557Sjimharris	major_status = GSS_S_FAILURE;
428230557Sjimharris    }
429230557Sjimharris    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
430230557Sjimharris    return major_status;
431230557Sjimharris}
432230557Sjimharris
433230557Sjimharrisstatic OM_uint32
434230557Sjimharrisget_authtime(OM_uint32 *minor_status,
435230557Sjimharris	     gsskrb5_ctx ctx,
436230557Sjimharris	     gss_buffer_set_t *data_set)
437230557Sjimharris
438230557Sjimharris{
439230557Sjimharris    gss_buffer_desc value;
440230557Sjimharris    unsigned char buf[4];
441230557Sjimharris    OM_uint32 authtime;
442230557Sjimharris
443230557Sjimharris    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
444230557Sjimharris    if (ctx->ticket == NULL) {
445230557Sjimharris	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
446230557Sjimharris	_gsskrb5_set_status(EINVAL, "No ticket to obtain auth time from");
447230557Sjimharris	*minor_status = EINVAL;
448230557Sjimharris	return GSS_S_FAILURE;
449230557Sjimharris    }
450230557Sjimharris
451230557Sjimharris    authtime = ctx->ticket->ticket.authtime;
452230557Sjimharris
453230557Sjimharris    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
454230557Sjimharris
455230557Sjimharris    _gsskrb5_encode_om_uint32(authtime, buf);
456230557Sjimharris    value.length = sizeof(buf);
457230557Sjimharris    value.value = buf;
458230557Sjimharris
459230557Sjimharris    return gss_add_buffer_set_member(minor_status,
460230557Sjimharris				     &value,
461230557Sjimharris				     data_set);
462230557Sjimharris}
463230557Sjimharris
464230557Sjimharris
465230557Sjimharrisstatic OM_uint32
466230557Sjimharrisget_service_keyblock
467230557Sjimharris        (OM_uint32 *minor_status,
468230557Sjimharris	 gsskrb5_ctx ctx,
469230557Sjimharris	 gss_buffer_set_t *data_set)
470230557Sjimharris{
471230557Sjimharris    krb5_storage *sp = NULL;
472230557Sjimharris    krb5_data data;
473230557Sjimharris    OM_uint32 maj_stat = GSS_S_COMPLETE;
474230557Sjimharris    krb5_error_code ret = EINVAL;
475230557Sjimharris
476230557Sjimharris    sp = krb5_storage_emem();
477230557Sjimharris    if (sp == NULL) {
478230557Sjimharris	_gsskrb5_clear_status();
479230557Sjimharris	*minor_status = ENOMEM;
480230557Sjimharris	return GSS_S_FAILURE;
481230557Sjimharris    }
482230557Sjimharris
483230557Sjimharris    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
484230557Sjimharris    if (ctx->service_keyblock == NULL) {
485230557Sjimharris	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
486230557Sjimharris	krb5_storage_free(sp);
487230557Sjimharris	_gsskrb5_set_status(EINVAL, "No service keyblock on gssapi context");
488230557Sjimharris	*minor_status = EINVAL;
489230557Sjimharris	return GSS_S_FAILURE;
490230557Sjimharris    }
491230557Sjimharris
492230557Sjimharris    krb5_data_zero(&data);
493230557Sjimharris
494230557Sjimharris    ret = krb5_store_keyblock(sp, *ctx->service_keyblock);
495230557Sjimharris
496230557Sjimharris    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
497230557Sjimharris
498230557Sjimharris    if (ret)
499230557Sjimharris	goto out;
500230557Sjimharris
501230557Sjimharris    ret = krb5_storage_to_data(sp, &data);
502230557Sjimharris    if (ret)
503230557Sjimharris	goto out;
504230557Sjimharris
505230557Sjimharris    {
506230557Sjimharris	gss_buffer_desc value;
507230557Sjimharris
508230557Sjimharris	value.length = data.length;
509230557Sjimharris	value.value = data.data;
510230557Sjimharris
511230557Sjimharris	maj_stat = gss_add_buffer_set_member(minor_status,
512230557Sjimharris					     &value,
513230557Sjimharris					     data_set);
514230557Sjimharris    }
515230557Sjimharris
516230557Sjimharrisout:
517230557Sjimharris    krb5_data_free(&data);
518230557Sjimharris    if (sp)
519230557Sjimharris	krb5_storage_free(sp);
520230557Sjimharris    if (ret) {
521230557Sjimharris	*minor_status = ret;
522230557Sjimharris	maj_stat = GSS_S_FAILURE;
523230557Sjimharris    }
524230557Sjimharris    return maj_stat;
525230557Sjimharris}
526230557Sjimharris/*
527230557Sjimharris *
528230557Sjimharris */
529230557Sjimharris
530230557SjimharrisOM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_sec_context_by_oid
531230557Sjimharris           (OM_uint32 *minor_status,
532230557Sjimharris            const gss_ctx_id_t context_handle,
533230557Sjimharris            const gss_OID desired_object,
534230557Sjimharris            gss_buffer_set_t *data_set)
535230557Sjimharris{
536230557Sjimharris    krb5_context context;
537230557Sjimharris    const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
538230557Sjimharris    unsigned suffix;
539230557Sjimharris
540230557Sjimharris    if (ctx == NULL) {
541	*minor_status = EINVAL;
542	return GSS_S_NO_CONTEXT;
543    }
544
545    GSSAPI_KRB5_INIT (&context);
546
547    if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) {
548	return inquire_sec_context_tkt_flags(minor_status,
549					     ctx,
550					     data_set);
551    } else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) {
552	return inquire_sec_context_has_updated_spnego(minor_status,
553						      ctx,
554						      data_set);
555    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) {
556	return inquire_sec_context_get_subkey(minor_status,
557					      ctx,
558					      context,
559					      TOKEN_KEY,
560					      data_set);
561    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) {
562	return inquire_sec_context_get_subkey(minor_status,
563					      ctx,
564					      context,
565					      INITIATOR_KEY,
566					      data_set);
567    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) {
568	return inquire_sec_context_get_subkey(minor_status,
569					      ctx,
570					      context,
571					      ACCEPTOR_KEY,
572					      data_set);
573    } else if (gss_oid_equal(desired_object, GSS_C_INQ_SSPI_SESSION_KEY)) {
574        return inquire_sec_context_get_sspi_session_key(minor_status,
575                                                        ctx,
576                                                        context,
577                                                        data_set);
578    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) {
579	return get_authtime(minor_status, ctx, data_set);
580    } else if (oid_prefix_equal(desired_object,
581				GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X,
582				&suffix)) {
583	return inquire_sec_context_authz_data(minor_status,
584					      ctx,
585					      context,
586					      suffix,
587					      data_set);
588    } else if (oid_prefix_equal(desired_object,
589				GSS_KRB5_EXPORT_LUCID_CONTEXT_X,
590				&suffix)) {
591	if (suffix == 1)
592	    return export_lucid_sec_context_v1(minor_status,
593					       ctx,
594					       context,
595					       data_set);
596	*minor_status = 0;
597	return GSS_S_FAILURE;
598    } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) {
599	return get_service_keyblock(minor_status, ctx, data_set);
600    } else {
601	*minor_status = 0;
602	return GSS_S_FAILURE;
603    }
604}
605
606