lib/gssapi/krb5: implement GSS_C_CHANNEL_BOUND_FLAG for gss_init_sec_context()
[heimdal.git] / lib / gssapi / krb5 / creds.c
blob036d9fa072a198088ff8f9b33c688ba0f3841d27
1 /*
2 * Copyright (c) 2009 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "gsskrb5_locl.h"
36 OM_uint32 GSSAPI_CALLCONV
37 _gsskrb5_export_cred(OM_uint32 *minor_status,
38 gss_cred_id_t cred_handle,
39 gss_buffer_t cred_token)
41 OM_uint32 major_status;
42 gsskrb5_cred handle = (gsskrb5_cred)cred_handle;
43 krb5_context context;
44 krb5_error_code ret;
45 krb5_storage *sp;
46 krb5_data data;
47 const char *type;
48 char *str;
50 GSSAPI_KRB5_INIT (&context);
52 if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) {
53 *minor_status = GSS_KRB5_S_G_BAD_USAGE;
54 return GSS_S_FAILURE;
57 sp = krb5_storage_emem();
58 if (sp == NULL) {
59 *minor_status = ENOMEM;
60 return GSS_S_FAILURE;
63 type = krb5_cc_get_type(context, handle->ccache);
64 if (strcmp(type, "MEMORY") == 0) {
65 krb5_creds *creds;
66 krb5_data config_start_realm;
67 char *start_realm;
69 ret = krb5_store_uint32(sp, 0);
70 if (ret) {
71 krb5_storage_free(sp);
72 *minor_status = ret;
73 return GSS_S_FAILURE;
76 ret = krb5_cc_get_config(context, handle->ccache, NULL, "start_realm",
77 &config_start_realm);
78 if (ret == 0) {
79 start_realm = strndup(config_start_realm.data,
80 config_start_realm.length);
81 krb5_data_free(&config_start_realm);
82 } else {
83 start_realm = strdup(krb5_principal_get_realm(context,
84 handle->principal));
86 if (start_realm == NULL) {
87 *minor_status = krb5_enomem(context);
88 krb5_storage_free(sp);
89 return GSS_S_FAILURE;
92 ret = _krb5_get_krbtgt(context, handle->ccache, start_realm, &creds);
93 free(start_realm);
94 start_realm = NULL;
95 if (ret) {
96 krb5_storage_free(sp);
97 *minor_status = ret;
98 return GSS_S_FAILURE;
101 ret = krb5_store_creds(sp, creds);
102 krb5_free_creds(context, creds);
103 if (ret) {
104 krb5_storage_free(sp);
105 *minor_status = ret;
106 return GSS_S_FAILURE;
109 } else {
110 ret = krb5_store_uint32(sp, 1);
111 if (ret) {
112 krb5_storage_free(sp);
113 *minor_status = ret;
114 return GSS_S_FAILURE;
117 ret = krb5_cc_get_full_name(context, handle->ccache, &str);
118 if (ret) {
119 krb5_storage_free(sp);
120 *minor_status = ret;
121 return GSS_S_FAILURE;
124 ret = krb5_store_string(sp, str);
125 free(str);
126 if (ret) {
127 krb5_storage_free(sp);
128 *minor_status = ret;
129 return GSS_S_FAILURE;
132 ret = krb5_storage_to_data(sp, &data);
133 krb5_storage_free(sp);
134 if (ret) {
135 *minor_status = ret;
136 return GSS_S_FAILURE;
138 sp = krb5_storage_emem();
139 if (sp == NULL) {
140 krb5_data_free(&data);
141 *minor_status = ENOMEM;
142 return GSS_S_FAILURE;
145 major_status = _gss_mg_store_oid(minor_status, sp, GSS_KRB5_MECHANISM);
146 if (major_status != GSS_S_COMPLETE) {
147 krb5_data_free(&data);
148 krb5_storage_free(sp);
149 return major_status;
152 ret = krb5_store_data(sp, data);
153 krb5_data_free(&data);
154 if (ret) {
155 krb5_storage_free(sp);
156 *minor_status = ret;
157 return GSS_S_FAILURE;
160 ret = krb5_storage_to_data(sp, &data);
161 krb5_storage_free(sp);
162 if (ret) {
163 *minor_status = ret;
164 return GSS_S_FAILURE;
167 cred_token->value = data.data;
168 cred_token->length = data.length;
170 return GSS_S_COMPLETE;
173 OM_uint32 GSSAPI_CALLCONV
174 _gsskrb5_import_cred(OM_uint32 * minor_status,
175 gss_buffer_t cred_token,
176 gss_cred_id_t * cred_handle)
178 krb5_context context;
179 krb5_error_code ret;
180 gsskrb5_cred handle;
181 krb5_ccache id;
182 krb5_storage *sp;
183 char *str;
184 uint32_t type;
185 int flags = 0;
187 *cred_handle = GSS_C_NO_CREDENTIAL;
189 GSSAPI_KRB5_INIT (&context);
191 sp = krb5_storage_from_mem(cred_token->value, cred_token->length);
192 if (sp == NULL) {
193 *minor_status = ENOMEM;
194 return GSS_S_FAILURE;
197 ret = krb5_ret_uint32(sp, &type);
198 if (ret) {
199 krb5_storage_free(sp);
200 *minor_status = ret;
201 return GSS_S_FAILURE;
203 switch (type) {
204 case 0: {
205 krb5_creds creds;
207 ret = krb5_ret_creds(sp, &creds);
208 krb5_storage_free(sp);
209 if (ret) {
210 *minor_status = ret;
211 return GSS_S_FAILURE;
214 ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id);
215 if (ret) {
216 *minor_status = ret;
217 return GSS_S_FAILURE;
220 ret = krb5_cc_initialize(context, id, creds.client);
221 if (ret) {
222 krb5_cc_destroy(context, id);
223 *minor_status = ret;
224 return GSS_S_FAILURE;
227 ret = krb5_cc_store_cred(context, id, &creds);
228 krb5_free_cred_contents(context, &creds);
229 if (ret) {
230 *minor_status = ret;
231 return GSS_S_FAILURE;
234 flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
236 break;
238 case 1:
239 ret = krb5_ret_string(sp, &str);
240 krb5_storage_free(sp);
241 if (ret) {
242 *minor_status = ret;
243 return GSS_S_FAILURE;
246 ret = krb5_cc_resolve(context, str, &id);
247 krb5_xfree(str);
248 if (ret) {
249 *minor_status = ret;
250 return GSS_S_FAILURE;
252 break;
254 default:
255 krb5_storage_free(sp);
256 *minor_status = 0;
257 return GSS_S_NO_CRED;
260 handle = calloc(1, sizeof(*handle));
261 if (handle == NULL) {
262 krb5_cc_close(context, id);
263 *minor_status = ENOMEM;
264 return GSS_S_FAILURE;
266 *minor_status = krb5_cc_get_principal(context, id, &handle->principal);
267 if (*minor_status) {
268 free(handle);
269 krb5_cc_close(context, id);
270 return GSS_S_FAILURE;
273 handle->usage = GSS_C_INITIATE;
274 handle->destination_realm = NULL;
275 handle->ccache = id;
276 handle->cred_flags = flags;
278 *cred_handle = (gss_cred_id_t)handle;
280 return GSS_S_COMPLETE;