creds.c revision 233294
143809Sjkh/*
243809Sjkh * Copyright (c) 2009 Kungliga Tekniska H��gskolan
387047Sru * (Royal Institute of Technology, Stockholm, Sweden).
443809Sjkh * All rights reserved.
543809Sjkh *
643809Sjkh * Redistribution and use in source and binary forms, with or without
743809Sjkh * modification, are permitted provided that the following conditions
843809Sjkh * are met:
959674Ssheldonh *
1059674Ssheldonh * 1. Redistributions of source code must retain the above copyright
1159674Ssheldonh *    notice, this list of conditions and the following disclaimer.
1254949Ssheldonh *
1343809Sjkh * 2. Redistributions in binary form must reproduce the above copyright
1443809Sjkh *    notice, this list of conditions and the following disclaimer in the
15140769Skeramida *    documentation and/or other materials provided with the distribution.
16140769Skeramida *
17140769Skeramida * 3. Neither the name of the Institute nor the names of its contributors
1850472Speter *    may be used to endorse or promote products derived from this software
1943809Sjkh *    without specific prior written permission.
2043809Sjkh *
2148290Sjseger * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2243809Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2343809Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24109233Smtm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25119170Smtm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26197619Sdougb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2798188Sgordon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28168358Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29153298Sdougb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30153298Sdougb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31153298Sdougb * SUCH DAMAGE.
32153298Sdougb */
3343809Sjkh
3448785Siwasaki#include "gsskrb5_locl.h"
3548785Siwasaki
3648785SiwasakiOM_uint32 GSSAPI_CALLCONV
37178450Sbrooks_gsskrb5_export_cred(OM_uint32 *minor_status,
38176835Sbrooks		     gss_cred_id_t cred_handle,
39131338Simp		     gss_buffer_t cred_token)
40152770Sjkoshy{
41112354Scjc    gsskrb5_cred handle = (gsskrb5_cred)cred_handle;
42112354Scjc    krb5_context context;
43112354Scjc    krb5_error_code ret;
44142580Snjl    krb5_storage *sp;
45142580Snjl    krb5_data data, mech;
46127345Sbrooks    const char *type;
47127345Sbrooks    char *str;
48167268Syar
49127345Sbrooks    GSSAPI_KRB5_INIT (&context);
50127345Sbrooks
51167268Syar    if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) {
52127345Sbrooks	*minor_status = GSS_KRB5_S_G_BAD_USAGE;
53153537Sdougb	return GSS_S_FAILURE;
54170085Sdougb    }
5579825Sroam
5643809Sjkh    sp = krb5_storage_emem();
57120195Sdougb    if (sp == NULL) {
58168410Spjd	*minor_status = ENOMEM;
59168410Spjd	return GSS_S_FAILURE;
60168410Spjd    }
61120195Sdougb
62120195Sdougb    type = krb5_cc_get_type(context, handle->ccache);
63120195Sdougb    if (strcmp(type, "MEMORY") == 0) {
64132356Ssimon	krb5_creds *creds;
65132356Ssimon	ret = krb5_store_uint32(sp, 0);
66120195Sdougb	if (ret) {
67149050Spjd	    krb5_storage_free(sp);
68149050Spjd	    *minor_status = ret;
69149050Spjd	    return GSS_S_FAILURE;
70149050Spjd	}
71149050Spjd
72149050Spjd	ret = _krb5_get_krbtgt(context, handle->ccache,
73149050Spjd			       handle->principal->realm,
74149050Spjd			       &creds);
75149050Spjd	if (ret) {
76149050Spjd	    krb5_storage_free(sp);
77149050Spjd	    *minor_status = ret;
78149050Spjd	    return GSS_S_FAILURE;
79149050Spjd	}
80149050Spjd
81148765Spjd	ret = krb5_store_creds(sp, creds);
82159377Sbrueffer	krb5_free_creds(context, creds);
83149050Spjd	if (ret) {
84149050Spjd	    krb5_storage_free(sp);
85136730Skeramida	    *minor_status = ret;
8687047Sru	    return GSS_S_FAILURE;
87193944Savg	}
8876946Sdd
89108018Smckusick    } else {
90138286Srees	ret = krb5_store_uint32(sp, 1);
9188676Ssheldonh	if (ret) {
9288676Ssheldonh	    krb5_storage_free(sp);
9343809Sjkh	    *minor_status = ret;
9443809Sjkh	    return GSS_S_FAILURE;
9543809Sjkh	}
9643809Sjkh
9743809Sjkh	ret = krb5_cc_get_full_name(context, handle->ccache, &str);
9864749Sjhb	if (ret) {
9948880Sjkh	    krb5_storage_free(sp);
100168546Spjd	    *minor_status = ret;
101168546Spjd	    return GSS_S_FAILURE;
10243809Sjkh	}
103115950Smtm
104168034Sache	ret = krb5_store_string(sp, str);
105168034Sache	free(str);
106190031Sdes	if (ret) {
107168033Sache	    krb5_storage_free(sp);
108179003Sbrooks	    *minor_status = ret;
109157706Sbrooks	    return GSS_S_FAILURE;
110188710Smtm	}
111178022Ssam    }
112178022Ssam    ret = krb5_storage_to_data(sp, &data);
113178022Ssam    krb5_storage_free(sp);
114178022Ssam    if (ret) {
11543809Sjkh	*minor_status = ret;
11645542Sdes	return GSS_S_FAILURE;
11743809Sjkh    }
11843809Sjkh    sp = krb5_storage_emem();
11987047Sru    if (sp == NULL) {
12057014Spaul	krb5_data_free(&data);
121200028Sume	*minor_status = ENOMEM;
122200028Sume	return GSS_S_FAILURE;
123200028Sume    }
124200028Sume
125181762Sjhb    mech.data = GSS_KRB5_MECHANISM->elements;
126181762Sjhb    mech.length = GSS_KRB5_MECHANISM->length;
127181762Sjhb
128181762Sjhb    ret = krb5_store_data(sp, mech);
129181762Sjhb    if (ret) {
130181762Sjhb	krb5_data_free(&data);
131181762Sjhb	krb5_storage_free(sp);
132181762Sjhb	*minor_status = ret;
133200028Sume	return GSS_S_FAILURE;
134200028Sume    }
135200028Sume
136200028Sume    ret = krb5_store_data(sp, data);
137200028Sume    krb5_data_free(&data);
138200028Sume    if (ret) {
139200028Sume	krb5_storage_free(sp);
140200028Sume	*minor_status = ret;
141163749Sphk	return GSS_S_FAILURE;
142181759Sjhb    }
143181759Sjhb
144181759Sjhb    ret = krb5_storage_to_data(sp, &data);
145181759Sjhb    krb5_storage_free(sp);
146202460Sume    if (ret) {
147181759Sjhb	*minor_status = ret;
148163749Sphk	return GSS_S_FAILURE;
149181759Sjhb    }
150163749Sphk
151181759Sjhb    cred_token->value = data.data;
152181759Sjhb    cred_token->length = data.length;
153175522Srafan
154175522Srafan    return GSS_S_COMPLETE;
155175522Srafan}
156175722Smtm
15761961SdillonOM_uint32 GSSAPI_CALLCONV
15861961Sdillon_gsskrb5_import_cred(OM_uint32 * minor_status,
159123029Sbms		     gss_buffer_t cred_token,
160123029Sbms		     gss_cred_id_t * cred_handle)
161123029Sbms{
16261961Sdillon    krb5_context context;
16361961Sdillon    krb5_error_code ret;
16444990Sbrian    gsskrb5_cred handle;
16587047Sru    krb5_ccache id;
16690957Scjc    krb5_storage *sp;
16787047Sru    char *str;
16866745Sdarrenr    uint32_t type;
16986856Sdarrenr    int flags = 0;
17066745Sdarrenr
17166745Sdarrenr    *cred_handle = GSS_C_NO_CREDENTIAL;
17286856Sdarrenr
17386856Sdarrenr    GSSAPI_KRB5_INIT (&context);
17486856Sdarrenr
17566745Sdarrenr    sp = krb5_storage_from_mem(cred_token->value, cred_token->length);
17666745Sdarrenr    if (sp == NULL) {
17786856Sdarrenr	*minor_status = ENOMEM;
17886856Sdarrenr	return GSS_S_FAILURE;
17986856Sdarrenr    }
18087047Sru
18185219Sdarrenr    ret = krb5_ret_uint32(sp, &type);
18286856Sdarrenr    if (ret) {
18385219Sdarrenr	krb5_storage_free(sp);
184127342Smlaier	*minor_status = ret;
185127342Smlaier	return GSS_S_FAILURE;
186127342Smlaier    }
187127342Smlaier    switch (type) {
188127759Smlaier    case 0: {
189132678Smlaier	krb5_creds creds;
190127759Smlaier
191127759Smlaier	ret = krb5_ret_creds(sp, &creds);
192172070Smlaier	krb5_storage_free(sp);
193172070Smlaier	if (ret) {
194150835Syar	    *minor_status = ret;
195150835Syar	    return GSS_S_FAILURE;
196168593Skeramida	}
197150835Syar
19877154Sobrien	ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id);
19989808Scjc	if (ret) {
20049704Sobrien	    *minor_status = ret;
20151209Sdes	    return GSS_S_FAILURE;
20260685Swollman	}
20395547Sdougb
20449603Sdes	ret = krb5_cc_initialize(context, id, creds.client);
20548687Speter	if (ret) {
20683677Sbrooks	    krb5_cc_destroy(context, id);
20783677Sbrooks	    *minor_status = ret;
20843809Sjkh	    return GSS_S_FAILURE;
20943809Sjkh	}
21064677Ssheldonh
211197145Shrs	ret = krb5_cc_store_cred(context, id, &creds);
212197145Shrs	krb5_free_cred_contents(context, &creds);
213137070Spjd
214201215Sjhb	flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
215201215Sjhb
216178738Sbrooks	break;
217189759Sbrooks    }
218152441Sbrooks    case 1:
21943809Sjkh	ret = krb5_ret_string(sp, &str);
220159138Sthompsa	krb5_storage_free(sp);
221159138Sthompsa	if (ret) {
222159138Sthompsa	    *minor_status = ret;
22343809Sjkh	    return GSS_S_FAILURE;
22443809Sjkh	}
22543809Sjkh
226179315Sbz	ret = krb5_cc_resolve(context, str, &id);
227179315Sbz	krb5_xfree(str);
228166583Sflz	if (ret) {
22977651Sbrian	    *minor_status = ret;
23077651Sbrian	    return GSS_S_FAILURE;
23177651Sbrian	}
23277651Sbrian	break;
233166583Sflz
234166583Sflz    default:
235166583Sflz	krb5_storage_free(sp);
236166583Sflz	*minor_status = 0;
23743809Sjkh	return GSS_S_NO_CRED;
23853665Salfred    }
23949110Sbrian
240138889Sbrian    handle = calloc(1, sizeof(*handle));
24149110Sbrian    if (handle == NULL) {
24249110Sbrian	krb5_cc_close(context, id);
24350193Sbrian	*minor_status = ENOMEM;
24449110Sbrian	return GSS_S_FAILURE;
24564471Sbrian    }
24649110Sbrian
247172586Semax    handle->usage = GSS_C_INITIATE;
248172586Semax    krb5_cc_get_principal(context, id, &handle->principal);
249172586Semax    handle->ccache = id;
250172586Semax    handle->cred_flags = flags;
251172586Semax
252172586Semax    *cred_handle = (gss_cred_id_t)handle;
25374462Salfred
254155236Sflz    return GSS_S_COMPLETE;
25543809Sjkh}
25678905Sdd