133f12199SDoug Rabson /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
433f12199SDoug Rabson * Copyright (c) 2005 Doug Rabson
533f12199SDoug Rabson * All rights reserved.
633f12199SDoug Rabson *
733f12199SDoug Rabson * Redistribution and use in source and binary forms, with or without
833f12199SDoug Rabson * modification, are permitted provided that the following conditions
933f12199SDoug Rabson * are met:
1033f12199SDoug Rabson * 1. Redistributions of source code must retain the above copyright
1133f12199SDoug Rabson * notice, this list of conditions and the following disclaimer.
1233f12199SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
1333f12199SDoug Rabson * notice, this list of conditions and the following disclaimer in the
1433f12199SDoug Rabson * documentation and/or other materials provided with the distribution.
1533f12199SDoug Rabson *
1633f12199SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1733f12199SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1833f12199SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1933f12199SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2033f12199SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2133f12199SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2233f12199SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2333f12199SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2433f12199SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2533f12199SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2633f12199SDoug Rabson * SUCH DAMAGE.
2733f12199SDoug Rabson */
2833f12199SDoug Rabson
2933f12199SDoug Rabson #include <gssapi/gssapi.h>
3033f12199SDoug Rabson #include <gssapi/gssapi_krb5.h>
3133f12199SDoug Rabson
3233f12199SDoug Rabson /* RCSID("$Id: gss_krb5.c 21889 2007-08-09 07:43:24Z lha $"); */
3333f12199SDoug Rabson
3433f12199SDoug Rabson #include <krb5.h>
3533f12199SDoug Rabson #include <roken.h>
36ae771770SStanislav Sedov #include <der.h>
3733f12199SDoug Rabson
3833f12199SDoug Rabson OM_uint32
gss_krb5_copy_ccache(OM_uint32 * minor_status,gss_cred_id_t cred,krb5_ccache out)3933f12199SDoug Rabson gss_krb5_copy_ccache(OM_uint32 *minor_status,
4033f12199SDoug Rabson gss_cred_id_t cred,
4133f12199SDoug Rabson krb5_ccache out)
4233f12199SDoug Rabson {
4333f12199SDoug Rabson gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
4433f12199SDoug Rabson krb5_context context;
4533f12199SDoug Rabson krb5_error_code kret;
4633f12199SDoug Rabson krb5_ccache id;
4733f12199SDoug Rabson OM_uint32 ret;
4833f12199SDoug Rabson char *str;
4933f12199SDoug Rabson
5033f12199SDoug Rabson ret = gss_inquire_cred_by_oid(minor_status,
5133f12199SDoug Rabson cred,
5233f12199SDoug Rabson GSS_KRB5_COPY_CCACHE_X,
5333f12199SDoug Rabson &data_set);
5433f12199SDoug Rabson if (ret)
5533f12199SDoug Rabson return ret;
5633f12199SDoug Rabson
5733f12199SDoug Rabson if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
5833f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
5933f12199SDoug Rabson *minor_status = EINVAL;
6033f12199SDoug Rabson return GSS_S_FAILURE;
6133f12199SDoug Rabson }
6233f12199SDoug Rabson
6333f12199SDoug Rabson kret = krb5_init_context(&context);
6433f12199SDoug Rabson if (kret) {
6533f12199SDoug Rabson *minor_status = kret;
6633f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
6733f12199SDoug Rabson return GSS_S_FAILURE;
6833f12199SDoug Rabson }
6933f12199SDoug Rabson
7033f12199SDoug Rabson kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length,
7133f12199SDoug Rabson (char *)data_set->elements[0].value);
7233f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
7333f12199SDoug Rabson if (kret == -1) {
7433f12199SDoug Rabson *minor_status = ENOMEM;
7533f12199SDoug Rabson return GSS_S_FAILURE;
7633f12199SDoug Rabson }
7733f12199SDoug Rabson
7833f12199SDoug Rabson kret = krb5_cc_resolve(context, str, &id);
7933f12199SDoug Rabson free(str);
8033f12199SDoug Rabson if (kret) {
8133f12199SDoug Rabson *minor_status = kret;
8233f12199SDoug Rabson return GSS_S_FAILURE;
8333f12199SDoug Rabson }
8433f12199SDoug Rabson
8533f12199SDoug Rabson kret = krb5_cc_copy_cache(context, id, out);
8633f12199SDoug Rabson krb5_cc_close(context, id);
8733f12199SDoug Rabson krb5_free_context(context);
8833f12199SDoug Rabson if (kret) {
8933f12199SDoug Rabson *minor_status = kret;
9033f12199SDoug Rabson return GSS_S_FAILURE;
9133f12199SDoug Rabson }
9233f12199SDoug Rabson
9333f12199SDoug Rabson return ret;
9433f12199SDoug Rabson }
9533f12199SDoug Rabson
9633f12199SDoug Rabson OM_uint32
gss_krb5_import_cred(OM_uint32 * minor_status,krb5_ccache id,krb5_principal keytab_principal,krb5_keytab keytab,gss_cred_id_t * cred)9733f12199SDoug Rabson gss_krb5_import_cred(OM_uint32 *minor_status,
9833f12199SDoug Rabson krb5_ccache id,
9933f12199SDoug Rabson krb5_principal keytab_principal,
10033f12199SDoug Rabson krb5_keytab keytab,
10133f12199SDoug Rabson gss_cred_id_t *cred)
10233f12199SDoug Rabson {
10333f12199SDoug Rabson gss_buffer_desc buffer;
10433f12199SDoug Rabson OM_uint32 major_status;
10533f12199SDoug Rabson krb5_context context;
10633f12199SDoug Rabson krb5_error_code ret;
10733f12199SDoug Rabson krb5_storage *sp;
10833f12199SDoug Rabson krb5_data data;
10933f12199SDoug Rabson char *str;
11033f12199SDoug Rabson
11133f12199SDoug Rabson *cred = GSS_C_NO_CREDENTIAL;
11233f12199SDoug Rabson
11333f12199SDoug Rabson ret = krb5_init_context(&context);
11433f12199SDoug Rabson if (ret) {
11533f12199SDoug Rabson *minor_status = ret;
11633f12199SDoug Rabson return GSS_S_FAILURE;
11733f12199SDoug Rabson }
11833f12199SDoug Rabson
11933f12199SDoug Rabson sp = krb5_storage_emem();
12033f12199SDoug Rabson if (sp == NULL) {
12133f12199SDoug Rabson *minor_status = ENOMEM;
12233f12199SDoug Rabson major_status = GSS_S_FAILURE;
12333f12199SDoug Rabson goto out;
12433f12199SDoug Rabson }
12533f12199SDoug Rabson
12633f12199SDoug Rabson if (id) {
12733f12199SDoug Rabson ret = krb5_cc_get_full_name(context, id, &str);
12833f12199SDoug Rabson if (ret == 0) {
12933f12199SDoug Rabson ret = krb5_store_string(sp, str);
13033f12199SDoug Rabson free(str);
13133f12199SDoug Rabson }
13233f12199SDoug Rabson } else
13333f12199SDoug Rabson ret = krb5_store_string(sp, "");
13433f12199SDoug Rabson if (ret) {
13533f12199SDoug Rabson *minor_status = ret;
13633f12199SDoug Rabson major_status = GSS_S_FAILURE;
13733f12199SDoug Rabson goto out;
13833f12199SDoug Rabson }
13933f12199SDoug Rabson
14033f12199SDoug Rabson if (keytab_principal) {
14133f12199SDoug Rabson ret = krb5_unparse_name(context, keytab_principal, &str);
14233f12199SDoug Rabson if (ret == 0) {
14333f12199SDoug Rabson ret = krb5_store_string(sp, str);
14433f12199SDoug Rabson free(str);
14533f12199SDoug Rabson }
14633f12199SDoug Rabson } else
14733f12199SDoug Rabson krb5_store_string(sp, "");
14833f12199SDoug Rabson if (ret) {
14933f12199SDoug Rabson *minor_status = ret;
15033f12199SDoug Rabson major_status = GSS_S_FAILURE;
15133f12199SDoug Rabson goto out;
15233f12199SDoug Rabson }
15333f12199SDoug Rabson
15433f12199SDoug Rabson
15533f12199SDoug Rabson if (keytab) {
15633f12199SDoug Rabson ret = krb5_kt_get_full_name(context, keytab, &str);
15733f12199SDoug Rabson if (ret == 0) {
15833f12199SDoug Rabson ret = krb5_store_string(sp, str);
15933f12199SDoug Rabson free(str);
16033f12199SDoug Rabson }
16133f12199SDoug Rabson } else
16233f12199SDoug Rabson krb5_store_string(sp, "");
16333f12199SDoug Rabson if (ret) {
16433f12199SDoug Rabson *minor_status = ret;
16533f12199SDoug Rabson major_status = GSS_S_FAILURE;
16633f12199SDoug Rabson goto out;
16733f12199SDoug Rabson }
16833f12199SDoug Rabson
16933f12199SDoug Rabson ret = krb5_storage_to_data(sp, &data);
17033f12199SDoug Rabson if (ret) {
17133f12199SDoug Rabson *minor_status = ret;
17233f12199SDoug Rabson major_status = GSS_S_FAILURE;
17333f12199SDoug Rabson goto out;
17433f12199SDoug Rabson }
17533f12199SDoug Rabson
17633f12199SDoug Rabson buffer.value = data.data;
17733f12199SDoug Rabson buffer.length = data.length;
17833f12199SDoug Rabson
17933f12199SDoug Rabson major_status = gss_set_cred_option(minor_status,
18033f12199SDoug Rabson cred,
18133f12199SDoug Rabson GSS_KRB5_IMPORT_CRED_X,
18233f12199SDoug Rabson &buffer);
18333f12199SDoug Rabson krb5_data_free(&data);
18433f12199SDoug Rabson out:
18533f12199SDoug Rabson if (sp)
18633f12199SDoug Rabson krb5_storage_free(sp);
18733f12199SDoug Rabson krb5_free_context(context);
18833f12199SDoug Rabson return major_status;
18933f12199SDoug Rabson }
19033f12199SDoug Rabson
19133f12199SDoug Rabson OM_uint32
gsskrb5_register_acceptor_identity(const char * identity)19233f12199SDoug Rabson gsskrb5_register_acceptor_identity(const char *identity)
19333f12199SDoug Rabson {
19433f12199SDoug Rabson gss_buffer_desc buffer;
19533f12199SDoug Rabson OM_uint32 junk;
19633f12199SDoug Rabson
19733f12199SDoug Rabson buffer.value = rk_UNCONST(identity);
19833f12199SDoug Rabson buffer.length = strlen(identity);
19933f12199SDoug Rabson
20033f12199SDoug Rabson gss_set_sec_context_option(&junk, NULL,
20133f12199SDoug Rabson GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer);
20233f12199SDoug Rabson
20333f12199SDoug Rabson return (GSS_S_COMPLETE);
20433f12199SDoug Rabson }
20533f12199SDoug Rabson
20633f12199SDoug Rabson OM_uint32
gsskrb5_set_dns_canonicalize(int flag)20733f12199SDoug Rabson gsskrb5_set_dns_canonicalize(int flag)
20833f12199SDoug Rabson {
20933f12199SDoug Rabson gss_buffer_desc buffer;
21033f12199SDoug Rabson OM_uint32 junk;
21133f12199SDoug Rabson char b = (flag != 0);
21233f12199SDoug Rabson
21333f12199SDoug Rabson buffer.value = &b;
21433f12199SDoug Rabson buffer.length = sizeof(b);
21533f12199SDoug Rabson
21633f12199SDoug Rabson gss_set_sec_context_option(&junk, NULL,
21733f12199SDoug Rabson GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer);
21833f12199SDoug Rabson
21933f12199SDoug Rabson return (GSS_S_COMPLETE);
22033f12199SDoug Rabson }
22133f12199SDoug Rabson
22233f12199SDoug Rabson
22333f12199SDoug Rabson
22433f12199SDoug Rabson static krb5_error_code
set_key(krb5_keyblock * keyblock,gss_krb5_lucid_key_t * key)22533f12199SDoug Rabson set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key)
22633f12199SDoug Rabson {
22733f12199SDoug Rabson key->type = keyblock->keytype;
22833f12199SDoug Rabson key->length = keyblock->keyvalue.length;
22933f12199SDoug Rabson key->data = malloc(key->length);
23033f12199SDoug Rabson if (key->data == NULL && key->length != 0)
23133f12199SDoug Rabson return ENOMEM;
23233f12199SDoug Rabson memcpy(key->data, keyblock->keyvalue.data, key->length);
23333f12199SDoug Rabson return 0;
23433f12199SDoug Rabson }
23533f12199SDoug Rabson
23633f12199SDoug Rabson static void
free_key(gss_krb5_lucid_key_t * key)23733f12199SDoug Rabson free_key(gss_krb5_lucid_key_t *key)
23833f12199SDoug Rabson {
23933f12199SDoug Rabson memset(key->data, 0, key->length);
24033f12199SDoug Rabson free(key->data);
24133f12199SDoug Rabson memset(key, 0, sizeof(*key));
24233f12199SDoug Rabson }
24333f12199SDoug Rabson
24433f12199SDoug Rabson OM_uint32
gss_krb5_export_lucid_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,OM_uint32 version,void ** rctx)24533f12199SDoug Rabson gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
24633f12199SDoug Rabson gss_ctx_id_t *context_handle,
24733f12199SDoug Rabson OM_uint32 version,
24833f12199SDoug Rabson void **rctx)
24933f12199SDoug Rabson {
25033f12199SDoug Rabson krb5_context context = NULL;
25133f12199SDoug Rabson krb5_error_code ret;
25233f12199SDoug Rabson gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
25333f12199SDoug Rabson OM_uint32 major_status;
25433f12199SDoug Rabson gss_krb5_lucid_context_v1_t *ctx = NULL;
25533f12199SDoug Rabson krb5_storage *sp = NULL;
25633f12199SDoug Rabson uint32_t num;
25733f12199SDoug Rabson
25833f12199SDoug Rabson if (context_handle == NULL
25933f12199SDoug Rabson || *context_handle == GSS_C_NO_CONTEXT
26033f12199SDoug Rabson || version != 1)
26133f12199SDoug Rabson {
26233f12199SDoug Rabson ret = EINVAL;
26333f12199SDoug Rabson return GSS_S_FAILURE;
26433f12199SDoug Rabson }
26533f12199SDoug Rabson
26633f12199SDoug Rabson major_status =
26733f12199SDoug Rabson gss_inquire_sec_context_by_oid (minor_status,
26833f12199SDoug Rabson *context_handle,
26933f12199SDoug Rabson GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X,
27033f12199SDoug Rabson &data_set);
27133f12199SDoug Rabson if (major_status)
27233f12199SDoug Rabson return major_status;
27333f12199SDoug Rabson
27433f12199SDoug Rabson if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
27533f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
27633f12199SDoug Rabson *minor_status = EINVAL;
27733f12199SDoug Rabson return GSS_S_FAILURE;
27833f12199SDoug Rabson }
27933f12199SDoug Rabson
28033f12199SDoug Rabson ret = krb5_init_context(&context);
28133f12199SDoug Rabson if (ret)
28233f12199SDoug Rabson goto out;
28333f12199SDoug Rabson
28433f12199SDoug Rabson ctx = calloc(1, sizeof(*ctx));
28533f12199SDoug Rabson if (ctx == NULL) {
28633f12199SDoug Rabson ret = ENOMEM;
28733f12199SDoug Rabson goto out;
28833f12199SDoug Rabson }
28933f12199SDoug Rabson
29033f12199SDoug Rabson sp = krb5_storage_from_mem(data_set->elements[0].value,
29133f12199SDoug Rabson data_set->elements[0].length);
29233f12199SDoug Rabson if (sp == NULL) {
29333f12199SDoug Rabson ret = ENOMEM;
29433f12199SDoug Rabson goto out;
29533f12199SDoug Rabson }
29633f12199SDoug Rabson
29733f12199SDoug Rabson ret = krb5_ret_uint32(sp, &num);
29833f12199SDoug Rabson if (ret) goto out;
29933f12199SDoug Rabson if (num != 1) {
30033f12199SDoug Rabson ret = EINVAL;
30133f12199SDoug Rabson goto out;
30233f12199SDoug Rabson }
30333f12199SDoug Rabson ctx->version = 1;
30433f12199SDoug Rabson /* initiator */
30533f12199SDoug Rabson ret = krb5_ret_uint32(sp, &ctx->initiate);
30633f12199SDoug Rabson if (ret) goto out;
30733f12199SDoug Rabson /* endtime */
30833f12199SDoug Rabson ret = krb5_ret_uint32(sp, &ctx->endtime);
30933f12199SDoug Rabson if (ret) goto out;
31033f12199SDoug Rabson /* send_seq */
31133f12199SDoug Rabson ret = krb5_ret_uint32(sp, &num);
31233f12199SDoug Rabson if (ret) goto out;
31333f12199SDoug Rabson ctx->send_seq = ((uint64_t)num) << 32;
31433f12199SDoug Rabson ret = krb5_ret_uint32(sp, &num);
31533f12199SDoug Rabson if (ret) goto out;
31633f12199SDoug Rabson ctx->send_seq |= num;
31733f12199SDoug Rabson /* recv_seq */
31833f12199SDoug Rabson ret = krb5_ret_uint32(sp, &num);
31933f12199SDoug Rabson if (ret) goto out;
32033f12199SDoug Rabson ctx->recv_seq = ((uint64_t)num) << 32;
32133f12199SDoug Rabson ret = krb5_ret_uint32(sp, &num);
32233f12199SDoug Rabson if (ret) goto out;
32333f12199SDoug Rabson ctx->recv_seq |= num;
32433f12199SDoug Rabson /* protocol */
32533f12199SDoug Rabson ret = krb5_ret_uint32(sp, &ctx->protocol);
32633f12199SDoug Rabson if (ret) goto out;
32733f12199SDoug Rabson if (ctx->protocol == 0) {
32833f12199SDoug Rabson krb5_keyblock key;
32933f12199SDoug Rabson
33033f12199SDoug Rabson /* sign_alg */
33133f12199SDoug Rabson ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg);
33233f12199SDoug Rabson if (ret) goto out;
33333f12199SDoug Rabson /* seal_alg */
33433f12199SDoug Rabson ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg);
33533f12199SDoug Rabson if (ret) goto out;
33633f12199SDoug Rabson /* ctx_key */
33733f12199SDoug Rabson ret = krb5_ret_keyblock(sp, &key);
33833f12199SDoug Rabson if (ret) goto out;
33933f12199SDoug Rabson ret = set_key(&key, &ctx->rfc1964_kd.ctx_key);
34033f12199SDoug Rabson krb5_free_keyblock_contents(context, &key);
34133f12199SDoug Rabson if (ret) goto out;
34233f12199SDoug Rabson } else if (ctx->protocol == 1) {
34333f12199SDoug Rabson krb5_keyblock key;
34433f12199SDoug Rabson
34533f12199SDoug Rabson /* acceptor_subkey */
34633f12199SDoug Rabson ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey);
34733f12199SDoug Rabson if (ret) goto out;
34833f12199SDoug Rabson /* ctx_key */
34933f12199SDoug Rabson ret = krb5_ret_keyblock(sp, &key);
35033f12199SDoug Rabson if (ret) goto out;
35133f12199SDoug Rabson ret = set_key(&key, &ctx->cfx_kd.ctx_key);
35233f12199SDoug Rabson krb5_free_keyblock_contents(context, &key);
35333f12199SDoug Rabson if (ret) goto out;
35433f12199SDoug Rabson /* acceptor_subkey */
35533f12199SDoug Rabson if (ctx->cfx_kd.have_acceptor_subkey) {
35633f12199SDoug Rabson ret = krb5_ret_keyblock(sp, &key);
35733f12199SDoug Rabson if (ret) goto out;
35833f12199SDoug Rabson ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey);
35933f12199SDoug Rabson krb5_free_keyblock_contents(context, &key);
36033f12199SDoug Rabson if (ret) goto out;
36133f12199SDoug Rabson }
36233f12199SDoug Rabson } else {
36333f12199SDoug Rabson ret = EINVAL;
36433f12199SDoug Rabson goto out;
36533f12199SDoug Rabson }
36633f12199SDoug Rabson
36733f12199SDoug Rabson *rctx = ctx;
36833f12199SDoug Rabson
36933f12199SDoug Rabson out:
37033f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
37133f12199SDoug Rabson if (sp)
37233f12199SDoug Rabson krb5_storage_free(sp);
37333f12199SDoug Rabson if (context)
37433f12199SDoug Rabson krb5_free_context(context);
37533f12199SDoug Rabson
37633f12199SDoug Rabson if (ret) {
37733f12199SDoug Rabson if (ctx)
37833f12199SDoug Rabson gss_krb5_free_lucid_sec_context(NULL, ctx);
37933f12199SDoug Rabson
38033f12199SDoug Rabson *minor_status = ret;
38133f12199SDoug Rabson return GSS_S_FAILURE;
38233f12199SDoug Rabson }
38333f12199SDoug Rabson *minor_status = 0;
38433f12199SDoug Rabson return GSS_S_COMPLETE;
38533f12199SDoug Rabson }
38633f12199SDoug Rabson
38733f12199SDoug Rabson OM_uint32
gss_krb5_free_lucid_sec_context(OM_uint32 * minor_status,void * c)38833f12199SDoug Rabson gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c)
38933f12199SDoug Rabson {
39033f12199SDoug Rabson gss_krb5_lucid_context_v1_t *ctx = c;
39133f12199SDoug Rabson
39233f12199SDoug Rabson if (ctx->version != 1) {
39333f12199SDoug Rabson if (minor_status)
39433f12199SDoug Rabson *minor_status = 0;
39533f12199SDoug Rabson return GSS_S_FAILURE;
39633f12199SDoug Rabson }
39733f12199SDoug Rabson
39833f12199SDoug Rabson if (ctx->protocol == 0) {
39933f12199SDoug Rabson free_key(&ctx->rfc1964_kd.ctx_key);
40033f12199SDoug Rabson } else if (ctx->protocol == 1) {
40133f12199SDoug Rabson free_key(&ctx->cfx_kd.ctx_key);
40233f12199SDoug Rabson if (ctx->cfx_kd.have_acceptor_subkey)
40333f12199SDoug Rabson free_key(&ctx->cfx_kd.acceptor_subkey);
40433f12199SDoug Rabson }
40533f12199SDoug Rabson free(ctx);
40633f12199SDoug Rabson if (minor_status)
40733f12199SDoug Rabson *minor_status = 0;
40833f12199SDoug Rabson return GSS_S_COMPLETE;
40933f12199SDoug Rabson }
41033f12199SDoug Rabson
41133f12199SDoug Rabson /*
41233f12199SDoug Rabson *
41333f12199SDoug Rabson */
41433f12199SDoug Rabson
41533f12199SDoug Rabson OM_uint32
gss_krb5_set_allowable_enctypes(OM_uint32 * minor_status,gss_cred_id_t cred,OM_uint32 num_enctypes,int32_t * enctypes)41633f12199SDoug Rabson gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
41733f12199SDoug Rabson gss_cred_id_t cred,
41833f12199SDoug Rabson OM_uint32 num_enctypes,
41933f12199SDoug Rabson int32_t *enctypes)
42033f12199SDoug Rabson {
42133f12199SDoug Rabson krb5_error_code ret;
42233f12199SDoug Rabson OM_uint32 maj_status;
42333f12199SDoug Rabson gss_buffer_desc buffer;
42433f12199SDoug Rabson krb5_storage *sp;
42533f12199SDoug Rabson krb5_data data;
42633f12199SDoug Rabson int i;
42733f12199SDoug Rabson
42833f12199SDoug Rabson sp = krb5_storage_emem();
42933f12199SDoug Rabson if (sp == NULL) {
43033f12199SDoug Rabson *minor_status = ENOMEM;
43133f12199SDoug Rabson maj_status = GSS_S_FAILURE;
43233f12199SDoug Rabson goto out;
43333f12199SDoug Rabson }
43433f12199SDoug Rabson
43533f12199SDoug Rabson for (i = 0; i < num_enctypes; i++) {
43633f12199SDoug Rabson ret = krb5_store_int32(sp, enctypes[i]);
43733f12199SDoug Rabson if (ret) {
43833f12199SDoug Rabson *minor_status = ret;
43933f12199SDoug Rabson maj_status = GSS_S_FAILURE;
44033f12199SDoug Rabson goto out;
44133f12199SDoug Rabson }
44233f12199SDoug Rabson }
44333f12199SDoug Rabson
44433f12199SDoug Rabson ret = krb5_storage_to_data(sp, &data);
44533f12199SDoug Rabson if (ret) {
44633f12199SDoug Rabson *minor_status = ret;
44733f12199SDoug Rabson maj_status = GSS_S_FAILURE;
44833f12199SDoug Rabson goto out;
44933f12199SDoug Rabson }
45033f12199SDoug Rabson
45133f12199SDoug Rabson buffer.value = data.data;
45233f12199SDoug Rabson buffer.length = data.length;
45333f12199SDoug Rabson
45433f12199SDoug Rabson maj_status = gss_set_cred_option(minor_status,
45533f12199SDoug Rabson &cred,
45633f12199SDoug Rabson GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X,
45733f12199SDoug Rabson &buffer);
45833f12199SDoug Rabson krb5_data_free(&data);
45933f12199SDoug Rabson out:
46033f12199SDoug Rabson if (sp)
46133f12199SDoug Rabson krb5_storage_free(sp);
46233f12199SDoug Rabson return maj_status;
46333f12199SDoug Rabson }
46433f12199SDoug Rabson
46533f12199SDoug Rabson /*
46633f12199SDoug Rabson *
46733f12199SDoug Rabson */
46833f12199SDoug Rabson
46933f12199SDoug Rabson OM_uint32
gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc * c)47033f12199SDoug Rabson gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
47133f12199SDoug Rabson {
47233f12199SDoug Rabson gss_buffer_desc buffer;
47333f12199SDoug Rabson OM_uint32 junk;
47433f12199SDoug Rabson
47533f12199SDoug Rabson if (c) {
47633f12199SDoug Rabson buffer.value = c;
47733f12199SDoug Rabson buffer.length = sizeof(*c);
47833f12199SDoug Rabson } else {
47933f12199SDoug Rabson buffer.value = NULL;
48033f12199SDoug Rabson buffer.length = 0;
48133f12199SDoug Rabson }
48233f12199SDoug Rabson
48333f12199SDoug Rabson gss_set_sec_context_option(&junk, NULL,
48433f12199SDoug Rabson GSS_KRB5_SEND_TO_KDC_X, &buffer);
48533f12199SDoug Rabson
48633f12199SDoug Rabson return (GSS_S_COMPLETE);
48733f12199SDoug Rabson }
48833f12199SDoug Rabson
48933f12199SDoug Rabson /*
49033f12199SDoug Rabson *
49133f12199SDoug Rabson */
49233f12199SDoug Rabson
49333f12199SDoug Rabson OM_uint32
gss_krb5_ccache_name(OM_uint32 * minor_status,const char * name,const char ** out_name)49433f12199SDoug Rabson gss_krb5_ccache_name(OM_uint32 *minor_status,
49533f12199SDoug Rabson const char *name,
49633f12199SDoug Rabson const char **out_name)
49733f12199SDoug Rabson {
49833f12199SDoug Rabson gss_buffer_desc buffer;
49933f12199SDoug Rabson OM_uint32 junk;
50033f12199SDoug Rabson
50133f12199SDoug Rabson if (out_name)
50233f12199SDoug Rabson *out_name = NULL;
50333f12199SDoug Rabson
50433f12199SDoug Rabson buffer.value = rk_UNCONST(name);
50533f12199SDoug Rabson buffer.length = strlen(name);
50633f12199SDoug Rabson
50733f12199SDoug Rabson gss_set_sec_context_option(&junk, NULL,
50833f12199SDoug Rabson GSS_KRB5_CCACHE_NAME_X, &buffer);
50933f12199SDoug Rabson
51033f12199SDoug Rabson return (GSS_S_COMPLETE);
51133f12199SDoug Rabson }
51233f12199SDoug Rabson
51333f12199SDoug Rabson
51433f12199SDoug Rabson /*
51533f12199SDoug Rabson *
51633f12199SDoug Rabson */
51733f12199SDoug Rabson
51833f12199SDoug Rabson OM_uint32
gsskrb5_extract_authtime_from_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,time_t * authtime)51933f12199SDoug Rabson gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
52033f12199SDoug Rabson gss_ctx_id_t context_handle,
52133f12199SDoug Rabson time_t *authtime)
52233f12199SDoug Rabson {
52333f12199SDoug Rabson gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
52433f12199SDoug Rabson OM_uint32 maj_stat;
52533f12199SDoug Rabson
52633f12199SDoug Rabson if (context_handle == GSS_C_NO_CONTEXT) {
52733f12199SDoug Rabson *minor_status = EINVAL;
52833f12199SDoug Rabson return GSS_S_FAILURE;
52933f12199SDoug Rabson }
53033f12199SDoug Rabson
53133f12199SDoug Rabson maj_stat =
53233f12199SDoug Rabson gss_inquire_sec_context_by_oid (minor_status,
53333f12199SDoug Rabson context_handle,
53433f12199SDoug Rabson GSS_KRB5_GET_AUTHTIME_X,
53533f12199SDoug Rabson &data_set);
53633f12199SDoug Rabson if (maj_stat)
53733f12199SDoug Rabson return maj_stat;
53833f12199SDoug Rabson
53933f12199SDoug Rabson if (data_set == GSS_C_NO_BUFFER_SET) {
54033f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
54133f12199SDoug Rabson *minor_status = EINVAL;
54233f12199SDoug Rabson return GSS_S_FAILURE;
54333f12199SDoug Rabson }
54433f12199SDoug Rabson
54533f12199SDoug Rabson if (data_set->count != 1) {
54633f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
54733f12199SDoug Rabson *minor_status = EINVAL;
54833f12199SDoug Rabson return GSS_S_FAILURE;
54933f12199SDoug Rabson }
55033f12199SDoug Rabson
55133f12199SDoug Rabson if (data_set->elements[0].length != 4) {
55233f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
55333f12199SDoug Rabson *minor_status = EINVAL;
55433f12199SDoug Rabson return GSS_S_FAILURE;
55533f12199SDoug Rabson }
55633f12199SDoug Rabson
55733f12199SDoug Rabson {
55833f12199SDoug Rabson unsigned char *buf = data_set->elements[0].value;
55933f12199SDoug Rabson *authtime = (buf[3] <<24) | (buf[2] << 16) |
56033f12199SDoug Rabson (buf[1] << 8) | (buf[0] << 0);
56133f12199SDoug Rabson }
56233f12199SDoug Rabson
56333f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
56433f12199SDoug Rabson
56533f12199SDoug Rabson *minor_status = 0;
56633f12199SDoug Rabson return GSS_S_COMPLETE;
56733f12199SDoug Rabson }
56833f12199SDoug Rabson
56933f12199SDoug Rabson /*
57033f12199SDoug Rabson *
57133f12199SDoug Rabson */
57233f12199SDoug Rabson
57333f12199SDoug Rabson OM_uint32
gsskrb5_extract_authz_data_from_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int ad_type,gss_buffer_t ad_data)57433f12199SDoug Rabson gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
57533f12199SDoug Rabson gss_ctx_id_t context_handle,
57633f12199SDoug Rabson int ad_type,
57733f12199SDoug Rabson gss_buffer_t ad_data)
57833f12199SDoug Rabson {
57933f12199SDoug Rabson gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
58033f12199SDoug Rabson OM_uint32 maj_stat;
58133f12199SDoug Rabson gss_OID_desc oid_flat;
58233f12199SDoug Rabson heim_oid baseoid, oid;
58333f12199SDoug Rabson size_t size;
58433f12199SDoug Rabson
58533f12199SDoug Rabson if (context_handle == GSS_C_NO_CONTEXT) {
58633f12199SDoug Rabson *minor_status = EINVAL;
58733f12199SDoug Rabson return GSS_S_FAILURE;
58833f12199SDoug Rabson }
58933f12199SDoug Rabson
59033f12199SDoug Rabson /* All this to append an integer to an oid... */
59133f12199SDoug Rabson
59233f12199SDoug Rabson if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
59333f12199SDoug Rabson GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
59433f12199SDoug Rabson &baseoid, NULL) != 0) {
59533f12199SDoug Rabson *minor_status = EINVAL;
59633f12199SDoug Rabson return GSS_S_FAILURE;
59733f12199SDoug Rabson }
59833f12199SDoug Rabson
59933f12199SDoug Rabson oid.length = baseoid.length + 1;
60033f12199SDoug Rabson oid.components = calloc(oid.length, sizeof(*oid.components));
60133f12199SDoug Rabson if (oid.components == NULL) {
60233f12199SDoug Rabson der_free_oid(&baseoid);
60333f12199SDoug Rabson
60433f12199SDoug Rabson *minor_status = ENOMEM;
60533f12199SDoug Rabson return GSS_S_FAILURE;
60633f12199SDoug Rabson }
60733f12199SDoug Rabson
60833f12199SDoug Rabson memcpy(oid.components, baseoid.components,
60933f12199SDoug Rabson baseoid.length * sizeof(*baseoid.components));
61033f12199SDoug Rabson
61133f12199SDoug Rabson der_free_oid(&baseoid);
61233f12199SDoug Rabson
61333f12199SDoug Rabson oid.components[oid.length - 1] = ad_type;
61433f12199SDoug Rabson
61533f12199SDoug Rabson oid_flat.length = der_length_oid(&oid);
61633f12199SDoug Rabson oid_flat.elements = malloc(oid_flat.length);
61733f12199SDoug Rabson if (oid_flat.elements == NULL) {
61833f12199SDoug Rabson free(oid.components);
61933f12199SDoug Rabson *minor_status = ENOMEM;
62033f12199SDoug Rabson return GSS_S_FAILURE;
62133f12199SDoug Rabson }
62233f12199SDoug Rabson
62333f12199SDoug Rabson if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
62433f12199SDoug Rabson oid_flat.length, &oid, &size) != 0) {
62533f12199SDoug Rabson free(oid.components);
62633f12199SDoug Rabson free(oid_flat.elements);
62733f12199SDoug Rabson *minor_status = EINVAL;
62833f12199SDoug Rabson return GSS_S_FAILURE;
62933f12199SDoug Rabson }
63033f12199SDoug Rabson if (oid_flat.length != size)
63133f12199SDoug Rabson abort();
63233f12199SDoug Rabson
63333f12199SDoug Rabson free(oid.components);
63433f12199SDoug Rabson
63533f12199SDoug Rabson /* FINALLY, we have the OID */
63633f12199SDoug Rabson
63733f12199SDoug Rabson maj_stat = gss_inquire_sec_context_by_oid (minor_status,
63833f12199SDoug Rabson context_handle,
63933f12199SDoug Rabson &oid_flat,
64033f12199SDoug Rabson &data_set);
64133f12199SDoug Rabson
64233f12199SDoug Rabson free(oid_flat.elements);
64333f12199SDoug Rabson
64433f12199SDoug Rabson if (maj_stat)
64533f12199SDoug Rabson return maj_stat;
64633f12199SDoug Rabson
64733f12199SDoug Rabson if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
64833f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
64933f12199SDoug Rabson *minor_status = EINVAL;
65033f12199SDoug Rabson return GSS_S_FAILURE;
65133f12199SDoug Rabson }
65233f12199SDoug Rabson
65333f12199SDoug Rabson ad_data->value = malloc(data_set->elements[0].length);
65433f12199SDoug Rabson if (ad_data->value == NULL) {
65533f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
65633f12199SDoug Rabson *minor_status = ENOMEM;
65733f12199SDoug Rabson return GSS_S_FAILURE;
65833f12199SDoug Rabson }
65933f12199SDoug Rabson
66033f12199SDoug Rabson ad_data->length = data_set->elements[0].length;
66133f12199SDoug Rabson memcpy(ad_data->value, data_set->elements[0].value, ad_data->length);
66233f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
66333f12199SDoug Rabson
66433f12199SDoug Rabson *minor_status = 0;
66533f12199SDoug Rabson return GSS_S_COMPLETE;
66633f12199SDoug Rabson }
66733f12199SDoug Rabson
66833f12199SDoug Rabson /*
66933f12199SDoug Rabson *
67033f12199SDoug Rabson */
67133f12199SDoug Rabson
67233f12199SDoug Rabson static OM_uint32
gsskrb5_extract_key(OM_uint32 * minor_status,gss_ctx_id_t context_handle,const gss_OID oid,krb5_keyblock ** keyblock)67333f12199SDoug Rabson gsskrb5_extract_key(OM_uint32 *minor_status,
67433f12199SDoug Rabson gss_ctx_id_t context_handle,
67533f12199SDoug Rabson const gss_OID oid,
67633f12199SDoug Rabson krb5_keyblock **keyblock)
67733f12199SDoug Rabson {
67833f12199SDoug Rabson krb5_error_code ret;
67933f12199SDoug Rabson gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
68033f12199SDoug Rabson OM_uint32 major_status;
68133f12199SDoug Rabson krb5_context context = NULL;
68233f12199SDoug Rabson krb5_storage *sp = NULL;
68333f12199SDoug Rabson
68433f12199SDoug Rabson if (context_handle == GSS_C_NO_CONTEXT) {
68533f12199SDoug Rabson ret = EINVAL;
68633f12199SDoug Rabson return GSS_S_FAILURE;
68733f12199SDoug Rabson }
68833f12199SDoug Rabson
68933f12199SDoug Rabson ret = krb5_init_context(&context);
69033f12199SDoug Rabson if(ret) {
69133f12199SDoug Rabson *minor_status = ret;
69233f12199SDoug Rabson return GSS_S_FAILURE;
69333f12199SDoug Rabson }
69433f12199SDoug Rabson
69533f12199SDoug Rabson major_status =
69633f12199SDoug Rabson gss_inquire_sec_context_by_oid (minor_status,
69733f12199SDoug Rabson context_handle,
69833f12199SDoug Rabson oid,
69933f12199SDoug Rabson &data_set);
70033f12199SDoug Rabson if (major_status)
70133f12199SDoug Rabson return major_status;
70233f12199SDoug Rabson
70333f12199SDoug Rabson if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
70433f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
70533f12199SDoug Rabson *minor_status = EINVAL;
70633f12199SDoug Rabson return GSS_S_FAILURE;
70733f12199SDoug Rabson }
70833f12199SDoug Rabson
70933f12199SDoug Rabson sp = krb5_storage_from_mem(data_set->elements[0].value,
71033f12199SDoug Rabson data_set->elements[0].length);
71133f12199SDoug Rabson if (sp == NULL) {
71233f12199SDoug Rabson ret = ENOMEM;
71333f12199SDoug Rabson goto out;
71433f12199SDoug Rabson }
71533f12199SDoug Rabson
71633f12199SDoug Rabson *keyblock = calloc(1, sizeof(**keyblock));
71733f12199SDoug Rabson if (keyblock == NULL) {
71833f12199SDoug Rabson ret = ENOMEM;
71933f12199SDoug Rabson goto out;
72033f12199SDoug Rabson }
72133f12199SDoug Rabson
72233f12199SDoug Rabson ret = krb5_ret_keyblock(sp, *keyblock);
72333f12199SDoug Rabson
72433f12199SDoug Rabson out:
72533f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
72633f12199SDoug Rabson if (sp)
72733f12199SDoug Rabson krb5_storage_free(sp);
72833f12199SDoug Rabson if (ret && keyblock) {
72933f12199SDoug Rabson krb5_free_keyblock(context, *keyblock);
73033f12199SDoug Rabson *keyblock = NULL;
73133f12199SDoug Rabson }
73233f12199SDoug Rabson if (context)
73333f12199SDoug Rabson krb5_free_context(context);
73433f12199SDoug Rabson
73533f12199SDoug Rabson *minor_status = ret;
73633f12199SDoug Rabson if (ret)
73733f12199SDoug Rabson return GSS_S_FAILURE;
73833f12199SDoug Rabson
73933f12199SDoug Rabson return GSS_S_COMPLETE;
74033f12199SDoug Rabson }
74133f12199SDoug Rabson
74233f12199SDoug Rabson /*
74333f12199SDoug Rabson *
74433f12199SDoug Rabson */
74533f12199SDoug Rabson
74633f12199SDoug Rabson OM_uint32
gsskrb5_extract_service_keyblock(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)74733f12199SDoug Rabson gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
74833f12199SDoug Rabson gss_ctx_id_t context_handle,
74933f12199SDoug Rabson krb5_keyblock **keyblock)
75033f12199SDoug Rabson {
75133f12199SDoug Rabson return gsskrb5_extract_key(minor_status,
75233f12199SDoug Rabson context_handle,
75333f12199SDoug Rabson GSS_KRB5_GET_SERVICE_KEYBLOCK_X,
75433f12199SDoug Rabson keyblock);
75533f12199SDoug Rabson }
75633f12199SDoug Rabson
75733f12199SDoug Rabson OM_uint32
gsskrb5_get_initiator_subkey(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)75833f12199SDoug Rabson gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
75933f12199SDoug Rabson gss_ctx_id_t context_handle,
76033f12199SDoug Rabson krb5_keyblock **keyblock)
76133f12199SDoug Rabson {
76233f12199SDoug Rabson return gsskrb5_extract_key(minor_status,
76333f12199SDoug Rabson context_handle,
76433f12199SDoug Rabson GSS_KRB5_GET_INITIATOR_SUBKEY_X,
76533f12199SDoug Rabson keyblock);
76633f12199SDoug Rabson }
76733f12199SDoug Rabson
76833f12199SDoug Rabson OM_uint32
gsskrb5_get_subkey(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)76933f12199SDoug Rabson gsskrb5_get_subkey(OM_uint32 *minor_status,
77033f12199SDoug Rabson gss_ctx_id_t context_handle,
77133f12199SDoug Rabson krb5_keyblock **keyblock)
77233f12199SDoug Rabson {
77333f12199SDoug Rabson return gsskrb5_extract_key(minor_status,
77433f12199SDoug Rabson context_handle,
77533f12199SDoug Rabson GSS_KRB5_GET_SUBKEY_X,
77633f12199SDoug Rabson keyblock);
77733f12199SDoug Rabson }
77833f12199SDoug Rabson
77933f12199SDoug Rabson OM_uint32
gsskrb5_set_default_realm(const char * realm)78033f12199SDoug Rabson gsskrb5_set_default_realm(const char *realm)
78133f12199SDoug Rabson {
78233f12199SDoug Rabson gss_buffer_desc buffer;
78333f12199SDoug Rabson OM_uint32 junk;
78433f12199SDoug Rabson
78533f12199SDoug Rabson buffer.value = rk_UNCONST(realm);
78633f12199SDoug Rabson buffer.length = strlen(realm);
78733f12199SDoug Rabson
78833f12199SDoug Rabson gss_set_sec_context_option(&junk, NULL,
78933f12199SDoug Rabson GSS_KRB5_SET_DEFAULT_REALM_X, &buffer);
79033f12199SDoug Rabson
79133f12199SDoug Rabson return (GSS_S_COMPLETE);
79233f12199SDoug Rabson }
79333f12199SDoug Rabson
79433f12199SDoug Rabson OM_uint32
gss_krb5_get_tkt_flags(OM_uint32 * minor_status,gss_ctx_id_t context_handle,OM_uint32 * tkt_flags)79533f12199SDoug Rabson gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
79633f12199SDoug Rabson gss_ctx_id_t context_handle,
79733f12199SDoug Rabson OM_uint32 *tkt_flags)
79833f12199SDoug Rabson {
79933f12199SDoug Rabson
80033f12199SDoug Rabson OM_uint32 major_status;
80133f12199SDoug Rabson gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
80233f12199SDoug Rabson
80333f12199SDoug Rabson if (context_handle == GSS_C_NO_CONTEXT) {
80433f12199SDoug Rabson *minor_status = EINVAL;
80533f12199SDoug Rabson return GSS_S_FAILURE;
80633f12199SDoug Rabson }
80733f12199SDoug Rabson
80833f12199SDoug Rabson major_status =
80933f12199SDoug Rabson gss_inquire_sec_context_by_oid (minor_status,
81033f12199SDoug Rabson context_handle,
81133f12199SDoug Rabson GSS_KRB5_GET_TKT_FLAGS_X,
81233f12199SDoug Rabson &data_set);
81333f12199SDoug Rabson if (major_status)
81433f12199SDoug Rabson return major_status;
81533f12199SDoug Rabson
81633f12199SDoug Rabson if (data_set == GSS_C_NO_BUFFER_SET ||
81733f12199SDoug Rabson data_set->count != 1 ||
81833f12199SDoug Rabson data_set->elements[0].length < 4) {
81933f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
82033f12199SDoug Rabson *minor_status = EINVAL;
82133f12199SDoug Rabson return GSS_S_FAILURE;
82233f12199SDoug Rabson }
82333f12199SDoug Rabson
82433f12199SDoug Rabson {
82533f12199SDoug Rabson const u_char *p = data_set->elements[0].value;
82633f12199SDoug Rabson *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
82733f12199SDoug Rabson }
82833f12199SDoug Rabson
82933f12199SDoug Rabson gss_release_buffer_set(minor_status, &data_set);
83033f12199SDoug Rabson return GSS_S_COMPLETE;
83133f12199SDoug Rabson }
83233f12199SDoug Rabson
833