xref: /freebsd/kerberos5/lib/libgssapi_krb5/gss_krb5.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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