1*d3273b5bSchristos /* $NetBSD: gss_cred.c,v 1.2 2017/01/28 21:31:46 christos Exp $ */
2ca1c9b0cSelric
3ca1c9b0cSelric /*
4ca1c9b0cSelric * Copyright (c) 2009 Kungliga Tekniska Högskolan
5ca1c9b0cSelric * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric * All rights reserved.
7ca1c9b0cSelric *
8ca1c9b0cSelric * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric * modification, are permitted provided that the following conditions
10ca1c9b0cSelric * are met:
11ca1c9b0cSelric *
12ca1c9b0cSelric * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric * notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric *
15ca1c9b0cSelric * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric * notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric * documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric *
19ca1c9b0cSelric * 3. Neither the name of KTH nor the names of its contributors may be
20ca1c9b0cSelric * used to endorse or promote products derived from this software without
21ca1c9b0cSelric * specific prior written permission.
22ca1c9b0cSelric *
23ca1c9b0cSelric * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
24ca1c9b0cSelric * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26ca1c9b0cSelric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
27ca1c9b0cSelric * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28ca1c9b0cSelric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29ca1c9b0cSelric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30ca1c9b0cSelric * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31ca1c9b0cSelric * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32ca1c9b0cSelric * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33ca1c9b0cSelric * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34ca1c9b0cSelric */
35ca1c9b0cSelric
36ca1c9b0cSelric #include "mech_locl.h"
37ca1c9b0cSelric #include <krb5/krb5.h>
38ca1c9b0cSelric
39ca1c9b0cSelric /*
40ca1c9b0cSelric * format: any number of:
41ca1c9b0cSelric * mech-len: int32
42ca1c9b0cSelric * mech-data: char * (not alligned)
43ca1c9b0cSelric * cred-len: int32
44ca1c9b0cSelric * cred-data char * (not alligned)
45ca1c9b0cSelric */
46ca1c9b0cSelric
47ca1c9b0cSelric GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_export_cred(OM_uint32 * minor_status,gss_cred_id_t cred_handle,gss_buffer_t token)48ca1c9b0cSelric gss_export_cred(OM_uint32 * minor_status,
49ca1c9b0cSelric gss_cred_id_t cred_handle,
50ca1c9b0cSelric gss_buffer_t token)
51ca1c9b0cSelric {
52ca1c9b0cSelric struct _gss_cred *cred = (struct _gss_cred *)cred_handle;
53ca1c9b0cSelric struct _gss_mechanism_cred *mc;
54ca1c9b0cSelric gss_buffer_desc buffer;
55ca1c9b0cSelric krb5_error_code ret;
56ca1c9b0cSelric krb5_storage *sp;
57ca1c9b0cSelric OM_uint32 major;
58ca1c9b0cSelric krb5_data data;
59ca1c9b0cSelric
60ca1c9b0cSelric _mg_buffer_zero(token);
61ca1c9b0cSelric
62ca1c9b0cSelric if (cred == NULL) {
63ca1c9b0cSelric *minor_status = 0;
64ca1c9b0cSelric return GSS_S_NO_CRED;
65ca1c9b0cSelric }
66ca1c9b0cSelric
67ca1c9b0cSelric HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
68ca1c9b0cSelric if (mc->gmc_mech->gm_export_cred == NULL) {
69ca1c9b0cSelric *minor_status = 0;
70ca1c9b0cSelric return GSS_S_NO_CRED;
71ca1c9b0cSelric }
72ca1c9b0cSelric }
73ca1c9b0cSelric
74ca1c9b0cSelric sp = krb5_storage_emem();
75ca1c9b0cSelric if (sp == NULL) {
76ca1c9b0cSelric *minor_status = ENOMEM;
77ca1c9b0cSelric return GSS_S_FAILURE;
78ca1c9b0cSelric }
79ca1c9b0cSelric
80ca1c9b0cSelric HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
81ca1c9b0cSelric
82ca1c9b0cSelric major = mc->gmc_mech->gm_export_cred(minor_status,
83ca1c9b0cSelric mc->gmc_cred, &buffer);
84ca1c9b0cSelric if (major) {
85ca1c9b0cSelric krb5_storage_free(sp);
86ca1c9b0cSelric return major;
87ca1c9b0cSelric }
88ca1c9b0cSelric
89ca1c9b0cSelric ret = krb5_storage_write(sp, buffer.value, buffer.length);
904f77a458Spettai if (ret < 0 || (size_t)ret != buffer.length) {
91ca1c9b0cSelric gss_release_buffer(minor_status, &buffer);
92ca1c9b0cSelric krb5_storage_free(sp);
93ca1c9b0cSelric *minor_status = EINVAL;
94ca1c9b0cSelric return GSS_S_FAILURE;
95ca1c9b0cSelric }
96ca1c9b0cSelric gss_release_buffer(minor_status, &buffer);
97ca1c9b0cSelric }
98ca1c9b0cSelric
99ca1c9b0cSelric ret = krb5_storage_to_data(sp, &data);
100ca1c9b0cSelric krb5_storage_free(sp);
101ca1c9b0cSelric if (ret) {
102ca1c9b0cSelric *minor_status = ret;
103ca1c9b0cSelric return GSS_S_FAILURE;
104ca1c9b0cSelric }
105ca1c9b0cSelric
106ca1c9b0cSelric token->value = data.data;
107ca1c9b0cSelric token->length = data.length;
108ca1c9b0cSelric
109ca1c9b0cSelric return GSS_S_COMPLETE;
110ca1c9b0cSelric }
111ca1c9b0cSelric
112ca1c9b0cSelric GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_import_cred(OM_uint32 * minor_status,gss_buffer_t token,gss_cred_id_t * cred_handle)113ca1c9b0cSelric gss_import_cred(OM_uint32 * minor_status,
114ca1c9b0cSelric gss_buffer_t token,
115ca1c9b0cSelric gss_cred_id_t * cred_handle)
116ca1c9b0cSelric {
117ca1c9b0cSelric gssapi_mech_interface m;
118ca1c9b0cSelric krb5_error_code ret;
119ca1c9b0cSelric struct _gss_cred *cred;
120ca1c9b0cSelric krb5_storage *sp = NULL;
121ca1c9b0cSelric OM_uint32 major, junk;
122ca1c9b0cSelric krb5_data data;
123ca1c9b0cSelric
124ca1c9b0cSelric *cred_handle = GSS_C_NO_CREDENTIAL;
125ca1c9b0cSelric
126ca1c9b0cSelric if (token->length == 0) {
127ca1c9b0cSelric *minor_status = ENOMEM;
128ca1c9b0cSelric return GSS_S_FAILURE;
129ca1c9b0cSelric }
130ca1c9b0cSelric
131ca1c9b0cSelric sp = krb5_storage_from_readonly_mem(token->value, token->length);
132ca1c9b0cSelric if (sp == NULL) {
133ca1c9b0cSelric *minor_status = ENOMEM;
134ca1c9b0cSelric return GSS_S_FAILURE;
135ca1c9b0cSelric }
136ca1c9b0cSelric
137ca1c9b0cSelric cred = calloc(1, sizeof(struct _gss_cred));
138ca1c9b0cSelric if (cred == NULL) {
139ca1c9b0cSelric krb5_storage_free(sp);
140ca1c9b0cSelric *minor_status = ENOMEM;
141ca1c9b0cSelric return GSS_S_FAILURE;
142ca1c9b0cSelric }
143ca1c9b0cSelric HEIM_SLIST_INIT(&cred->gc_mc);
144ca1c9b0cSelric
145ca1c9b0cSelric *cred_handle = (gss_cred_id_t)cred;
146ca1c9b0cSelric
147ca1c9b0cSelric while(1) {
148ca1c9b0cSelric struct _gss_mechanism_cred *mc;
149ca1c9b0cSelric gss_buffer_desc buffer;
150ca1c9b0cSelric gss_cred_id_t mcred;
151ca1c9b0cSelric gss_OID_desc oid;
152ca1c9b0cSelric
153ca1c9b0cSelric ret = krb5_ret_data(sp, &data);
154ca1c9b0cSelric if (ret == HEIM_ERR_EOF) {
155ca1c9b0cSelric break;
156ca1c9b0cSelric } else if (ret) {
157ca1c9b0cSelric *minor_status = ret;
158ca1c9b0cSelric major = GSS_S_FAILURE;
159ca1c9b0cSelric goto out;
160ca1c9b0cSelric }
161ca1c9b0cSelric oid.elements = data.data;
162ca1c9b0cSelric oid.length = data.length;
163ca1c9b0cSelric
164ca1c9b0cSelric m = __gss_get_mechanism(&oid);
165ca1c9b0cSelric krb5_data_free(&data);
166ca1c9b0cSelric if (!m) {
167ca1c9b0cSelric *minor_status = 0;
168ca1c9b0cSelric major = GSS_S_BAD_MECH;
169ca1c9b0cSelric goto out;
170ca1c9b0cSelric }
171ca1c9b0cSelric
172ca1c9b0cSelric if (m->gm_import_cred == NULL) {
173ca1c9b0cSelric *minor_status = 0;
174ca1c9b0cSelric major = GSS_S_BAD_MECH;
175ca1c9b0cSelric goto out;
176ca1c9b0cSelric }
177ca1c9b0cSelric
178ca1c9b0cSelric ret = krb5_ret_data(sp, &data);
179ca1c9b0cSelric if (ret) {
180ca1c9b0cSelric *minor_status = ret;
181ca1c9b0cSelric major = GSS_S_FAILURE;
182ca1c9b0cSelric goto out;
183ca1c9b0cSelric }
184ca1c9b0cSelric
185ca1c9b0cSelric buffer.value = data.data;
186ca1c9b0cSelric buffer.length = data.length;
187ca1c9b0cSelric
188ca1c9b0cSelric major = m->gm_import_cred(minor_status,
189ca1c9b0cSelric &buffer, &mcred);
190ca1c9b0cSelric krb5_data_free(&data);
191ca1c9b0cSelric if (major) {
192ca1c9b0cSelric goto out;
193ca1c9b0cSelric }
194ca1c9b0cSelric
195ca1c9b0cSelric mc = malloc(sizeof(struct _gss_mechanism_cred));
196ca1c9b0cSelric if (mc == NULL) {
197ca1c9b0cSelric *minor_status = EINVAL;
198ca1c9b0cSelric major = GSS_S_FAILURE;
199ca1c9b0cSelric goto out;
200ca1c9b0cSelric }
201ca1c9b0cSelric
202ca1c9b0cSelric mc->gmc_mech = m;
203ca1c9b0cSelric mc->gmc_mech_oid = &m->gm_mech_oid;
204ca1c9b0cSelric mc->gmc_cred = mcred;
205ca1c9b0cSelric
206ca1c9b0cSelric HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
207ca1c9b0cSelric }
208ca1c9b0cSelric krb5_storage_free(sp);
209ca1c9b0cSelric sp = NULL;
210ca1c9b0cSelric
211ca1c9b0cSelric if (HEIM_SLIST_EMPTY(&cred->gc_mc)) {
212ca1c9b0cSelric major = GSS_S_NO_CRED;
213ca1c9b0cSelric goto out;
214ca1c9b0cSelric }
215ca1c9b0cSelric
216ca1c9b0cSelric return GSS_S_COMPLETE;
217ca1c9b0cSelric
218ca1c9b0cSelric out:
219ca1c9b0cSelric if (sp)
220ca1c9b0cSelric krb5_storage_free(sp);
221ca1c9b0cSelric
222ca1c9b0cSelric gss_release_cred(&junk, cred_handle);
223ca1c9b0cSelric
224ca1c9b0cSelric return major;
225ca1c9b0cSelric
226ca1c9b0cSelric }
227