2 * Copyright (c) 2010, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include "gssapiP_eap.h"
36 * Fast reauthentication support for EAP GSS.
39 #define KRB5_AUTHDATA_RADIUS_AVP 513
41 static krb5_error_code
42 getAcceptorKey(krb5_context krbContext,
45 krb5_principal *princ,
49 krb5_keytab keytab = NULL;
50 krb5_keytab_entry ktent;
51 krb5_kt_cursor cursor = NULL;
54 memset(key, 0, sizeof(*key));
55 memset(&ktent, 0, sizeof(ktent));
57 code = krb5_kt_default(krbContext, &keytab);
61 if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
62 code = krb5_kt_get_entry(krbContext, keytab,
63 cred->name->krbPrincipal, 0,
64 ctx->encryptionType, &ktent);
68 code = krb5_kt_start_seq_get(krbContext, keytab, &cursor);
72 while ((code = krb5_kt_next_entry(krbContext, keytab,
73 &ktent, &cursor)) == 0) {
74 if (ktent.key.enctype != ctx->encryptionType) {
75 krb5_free_keytab_entry_contents(krbContext, &ktent);
81 code = krb5_copy_principal(krbContext, ktent.principal, princ);
85 code = krb5_copy_keyblock_contents(krbContext, &ktent.key, key);
90 if (cred == GSS_C_NO_CREDENTIAL || cred->name == GSS_C_NO_NAME)
91 krb5_kt_end_seq_get(krbContext, keytab, &cursor);
93 krb5_free_keytab_entry_contents(krbContext, &ktent);
94 krb5_kt_end_seq_get(krbContext, keytab, &cursor);
95 krb5_kt_close(krbContext, keytab);
99 krb5_free_principal(krbContext, *princ);
102 krb5_free_keyblock_contents(krbContext, key),
103 memset(key, 0, sizeof(key));
110 makeReauthCreds(OM_uint32 *minor,
113 gss_buffer_t credBuf)
115 OM_uint32 major = GSS_S_COMPLETE, code;
116 krb5_context krbContext = NULL;
117 krb5_ticket ticket = { 0 };
118 krb5_keyblock session, acceptorKey = { 0 };
119 krb5_enc_tkt_part enc_part = { 0 };
120 gss_buffer_desc attrBuf = GSS_C_EMPTY_BUFFER;
121 krb5_authdata *authData[2], authDatum = { 0 };
122 krb5_data *ticketData = NULL, *credsData = NULL;
123 krb5_creds creds = { 0 };
124 krb5_auth_context authContext = NULL;
127 credBuf->value = NULL;
129 GSSEAP_KRB_INIT(&krbContext);
131 code = getAcceptorKey(krbContext, ctx, cred,
132 &ticket.server, &acceptorKey);
136 enc_part.flags = TKT_FLG_INITIAL;
138 code = krb5_c_make_random_key(krbContext, ctx->encryptionType,
143 enc_part.session = &session;
144 enc_part.client = ctx->initiatorName->krbPrincipal;
145 enc_part.times.authtime = time(NULL);
146 enc_part.times.starttime = enc_part.times.authtime;
147 enc_part.times.endtime = ctx->expiryTime
150 enc_part.times.renew_till = 0;
152 major = gssEapExportAttrContext(minor, ctx->initiatorName,
154 if (GSS_ERROR(major))
157 authDatum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
158 authDatum.length = attrBuf.length;
159 authDatum.contents = attrBuf.value;
160 authData[0] = &authDatum;
162 enc_part.authorization_data = authData;
164 ticket.enc_part2 = &enc_part;
166 code = encode_krb5_ticket(&ticket, &ticketData);
170 creds.client = enc_part.client;
171 creds.server = ticket.server;
172 creds.keyblock = session;
173 creds.times = enc_part.times;
174 creds.ticket_flags = enc_part.flags;
175 creds.ticket = *ticketData;
176 creds.authdata = authData;
178 code = krb5_auth_con_init(krbContext, &authContext);
182 code = krb5_auth_con_setsendsubkey(krbContext, authContext, &ctx->rfc3961Key);
186 code = krb5_mk_1cred(krbContext, authContext, &creds, &credsData, NULL);
190 krbDataToGssBuffer(credsData, credBuf);
192 code = krb5_encrypt_tkt_part(krbContext, acceptorKey, &ticket);
199 if (ticket.enc_part.ciphertext.data != NULL)
200 GSSEAP_FREE(ticket.enc_part.ciphertext.data);
202 krb5_free_keyblock_contents(krbContext, &session);
203 krb5_free_keyblock_contents(krbContext, &acceptorKey);
204 gss_release_buffer(&code, &attrBuf);
205 krb5_free_data(krbContext, ticketData);
206 krb5_auth_con_free(krbContext, authContext);
207 if (credsData != NULL)
208 GSSEAP_FREE(credsData);
210 if (major == GSS_S_COMPLETE)
211 major = *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
217 storeReauthCreds(OM_uint32 *minor,
220 gss_buffer_t credBuf)
222 OM_uint32 major = GSS_S_COMPLETE, code;
223 krb5_context krbContext = NULL;
224 krb5_auth_context authContext = NULL;
225 krb5_data credData = { 0 };
226 krb5_creds **creds = NULL;
229 if (credBuf->length == 0 || cred == GSS_C_NO_CREDENTIAL)
230 return GSS_S_COMPLETE;
232 GSSEAP_KRB_INIT(&krbContext);
234 code = krb5_auth_con_init(krbContext, &authContext);
238 code = krb5_auth_con_setrecvsubkey(krbContext, authContext,
243 gssBufferToKrbData(credBuf, &credData);
245 code = krb5_rd_cred(krbContext, authContext, &credData, &creds, NULL);
252 OM_uint32 KRB5_CALLCONV
253 gss_krb5_import_cred(OM_uint32 *minor_status,
255 krb5_principal keytab_principal,
257 gss_cred_id_t *cred);
260 if (creds != NULL && creds[0] != NULL) {
266 krb5_auth_con_free(krbContext, authContext);
268 for (i = 0; creds[i] != NULL; i++)
269 krb5_free_creds(krbContext, creds[i]);
271 if (major == GSS_S_COMPLETE)
272 major = *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;