2 * Copyright (c) 2011, 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
34 * General mechanism utility routines.
37 #include "gssapiP_eap.h"
40 * 1.3.6.1.4.1.5322(padl)
43 * eap-aes128-cts-hmac-sha1-96(17)
44 * eap-aes256-cts-hmac-sha1-96(18)
47 * inquireSecContextByOid(1)
49 * setSecContextOption(3)
55 * Note: the enctype-less OID is used as the mechanism OID in exported
56 * names. There is no public symbol for it. This is consistent with
57 * the krb5 mechanism which, whilst known by many OIDs, always uses a
58 * canonical OID for exported names. (This OID is also returned by
61 static gss_OID_desc gssEapMechOids[] = {
62 /* 1.3.6.1.4.1.5322.22.1 */
63 { 9, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01" },
64 /* 1.3.6.1.4.1.5322.22.1.17 */
65 { 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01\x11" },
66 /* 1.3.6.1.4.1.5322.22.1.18 */
67 { 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01\x12" }
70 gss_OID GSS_EAP_MECHANISM = &gssEapMechOids[0];
71 gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM = &gssEapMechOids[1];
72 gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM = &gssEapMechOids[2];
75 * Returns TRUE is the OID is a concrete mechanism OID, that is, one
76 * with a Kerberos enctype as the last element.
79 gssEapIsConcreteMechanismOid(const gss_OID oid)
81 return oid->length > GSS_EAP_MECHANISM->length &&
82 memcmp(oid->elements, GSS_EAP_MECHANISM->elements,
83 GSS_EAP_MECHANISM->length) == 0;
87 gssEapIsMechanismOid(const gss_OID oid)
89 return oid == GSS_C_NO_OID ||
90 oidEqual(oid, GSS_EAP_MECHANISM) ||
91 gssEapIsConcreteMechanismOid(oid);
95 * Validate that all elements are concrete mechanism OIDs.
98 gssEapValidateMechs(OM_uint32 *minor,
99 const gss_OID_set mechs)
105 if (mechs == GSS_C_NO_OID_SET) {
106 return GSS_S_COMPLETE;
109 for (i = 0; i < mechs->count; i++) {
110 gss_OID oid = &mechs->elements[i];
112 if (!gssEapIsConcreteMechanismOid(oid)) {
113 *minor = GSSEAP_WRONG_MECH;
114 return GSS_S_BAD_MECH;
118 return GSS_S_COMPLETE;
122 gssEapOidToEnctype(OM_uint32 *minor,
124 krb5_enctype *enctype)
129 major = decomposeOid(minor,
130 GSS_EAP_MECHANISM->elements,
131 GSS_EAP_MECHANISM->length,
134 if (major == GSS_S_COMPLETE)
141 gssEapEnctypeToOid(OM_uint32 *minor,
142 krb5_enctype enctype,
150 oid = (gss_OID)GSSEAP_MALLOC(sizeof(*oid));
153 return GSS_S_FAILURE;
156 oid->length = GSS_EAP_MECHANISM->length + 1;
157 oid->elements = GSSEAP_MALLOC(oid->length);
158 if (oid->elements == NULL) {
161 return GSS_S_FAILURE;
164 major = composeOid(minor,
165 GSS_EAP_MECHANISM->elements,
166 GSS_EAP_MECHANISM->length,
169 if (major == GSS_S_COMPLETE) {
170 gssEapInternalizeOid(oid, pOid);
173 GSSEAP_FREE(oid->elements);
181 gssEapIndicateMechs(OM_uint32 *minor,
184 krb5_context krbContext;
185 OM_uint32 major, tmpMinor;
186 krb5_enctype *etypes;
189 GSSEAP_KRB_INIT(&krbContext);
191 *minor = krb5_get_permitted_enctypes(krbContext, &etypes);
193 return GSS_S_FAILURE;
196 major = gss_create_empty_oid_set(minor, mechs);
197 if (GSS_ERROR(major)) {
202 for (i = 0; etypes[i] != ENCTYPE_NULL; i++) {
205 /* XXX currently we aren't equipped to encode these enctypes */
206 if (etypes[i] < 0 || etypes[i] > 127)
209 major = gssEapEnctypeToOid(minor, etypes[i], &mechOid);
210 if (GSS_ERROR(major))
213 major = gss_add_oid_set_member(minor, mechOid, mechs);
214 if (GSS_ERROR(major))
217 gss_release_oid(&tmpMinor, &mechOid);
227 gssEapDefaultMech(OM_uint32 *minor,
231 OM_uint32 major, tmpMinor;
233 major = gssEapIndicateMechs(minor, &mechs);
234 if (GSS_ERROR(major)) {
238 if (mechs->count == 0) {
239 gss_release_oid_set(&tmpMinor, &mechs);
240 return GSS_S_BAD_MECH;
243 if (!gssEapInternalizeOid(&mechs->elements[0], oid)) {
244 /* don't double-free if we didn't internalize it */
245 mechs->elements[0].length = 0;
246 mechs->elements[0].elements = NULL;
249 gss_release_oid_set(&tmpMinor, &mechs);
252 return GSS_S_COMPLETE;
256 gssEapInternalizeOid(const gss_OID oid,
257 gss_OID *const pInternalizedOid)
261 *pInternalizedOid = GSS_C_NO_OID;
264 i < sizeof(gssEapMechOids) / sizeof(gssEapMechOids[0]);
266 if (oidEqual(oid, &gssEapMechOids[i])) {
267 *pInternalizedOid = (const gss_OID)&gssEapMechOids[i];
272 if (*pInternalizedOid == GSS_C_NO_OID) {
273 if (oidEqual(oid, GSS_EAP_NT_PRINCIPAL_NAME))
274 *pInternalizedOid = (const gss_OID)GSS_EAP_NT_PRINCIPAL_NAME;
277 if (*pInternalizedOid == GSS_C_NO_OID) {
278 *pInternalizedOid = oid;
286 gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid)
288 gss_OID internalizedOid = GSS_C_NO_OID;
292 if (gssEapInternalizeOid(*oid, &internalizedOid)) {
293 /* OID was internalized, so we can mark it as "freed" */
295 return GSS_S_COMPLETE;
298 /* we don't know about this OID */
299 return GSS_S_CONTINUE_NEEDED;
302 static gss_buffer_desc gssEapSaslMechs[] = {
303 { sizeof("EAP") - 1, "EAP", }, /* not used */
304 { sizeof("EAP-AES128") - 1, "EAP-AES128" },
305 { sizeof("EAP-AES256") - 1, "EAP-AES256" },
309 gssEapOidToSaslName(const gss_OID oid)
313 for (i = 1; i < sizeof(gssEapMechOids)/sizeof(gssEapMechOids[0]); i++) {
314 if (oidEqual(&gssEapMechOids[i], oid))
315 return &gssEapSaslMechs[i];
318 return GSS_C_NO_BUFFER;
322 gssEapSaslNameToOid(const gss_buffer_t name)
326 for (i = 1; i < sizeof(gssEapSaslMechs)/sizeof(gssEapSaslMechs[0]); i++) {
327 if (bufferEqual(&gssEapSaslMechs[i], name))
328 return &gssEapMechOids[i];