1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* lib/gssapi/mechglue/g_mechattr.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright (C) 2010 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All rights reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert #include "mglueP.h"
28*7f2fe78bSCy Schubert
29*7f2fe78bSCy Schubert static int
testMechAttr(gss_const_OID attr,gss_const_OID_set against)30*7f2fe78bSCy Schubert testMechAttr(gss_const_OID attr,
31*7f2fe78bSCy Schubert gss_const_OID_set against)
32*7f2fe78bSCy Schubert {
33*7f2fe78bSCy Schubert int present = 0;
34*7f2fe78bSCy Schubert OM_uint32 minor;
35*7f2fe78bSCy Schubert
36*7f2fe78bSCy Schubert if (GSS_ERROR(generic_gss_test_oid_set_member(&minor, attr,
37*7f2fe78bSCy Schubert (gss_OID_set)against,
38*7f2fe78bSCy Schubert &present)))
39*7f2fe78bSCy Schubert return 0;
40*7f2fe78bSCy Schubert
41*7f2fe78bSCy Schubert return present;
42*7f2fe78bSCy Schubert }
43*7f2fe78bSCy Schubert
44*7f2fe78bSCy Schubert /*
45*7f2fe78bSCy Schubert * Return TRUE iff all the elements of desired and none of the elements
46*7f2fe78bSCy Schubert * of except exist in available.
47*7f2fe78bSCy Schubert */
48*7f2fe78bSCy Schubert static int
testMechAttrsOffered(gss_const_OID_set desired,gss_const_OID_set except,gss_const_OID_set available)49*7f2fe78bSCy Schubert testMechAttrsOffered(gss_const_OID_set desired,
50*7f2fe78bSCy Schubert gss_const_OID_set except,
51*7f2fe78bSCy Schubert gss_const_OID_set available)
52*7f2fe78bSCy Schubert {
53*7f2fe78bSCy Schubert size_t i;
54*7f2fe78bSCy Schubert
55*7f2fe78bSCy Schubert if (desired != GSS_C_NO_OID_SET) {
56*7f2fe78bSCy Schubert for (i = 0; i < desired->count; i++) {
57*7f2fe78bSCy Schubert if (!testMechAttr(&desired->elements[i], available))
58*7f2fe78bSCy Schubert return 0;
59*7f2fe78bSCy Schubert }
60*7f2fe78bSCy Schubert }
61*7f2fe78bSCy Schubert
62*7f2fe78bSCy Schubert if (except != GSS_C_NO_OID_SET) {
63*7f2fe78bSCy Schubert for (i = 0; i < except->count; i++) {
64*7f2fe78bSCy Schubert if (testMechAttr(&except->elements[i], available))
65*7f2fe78bSCy Schubert return 0;
66*7f2fe78bSCy Schubert }
67*7f2fe78bSCy Schubert }
68*7f2fe78bSCy Schubert
69*7f2fe78bSCy Schubert return 1;
70*7f2fe78bSCy Schubert }
71*7f2fe78bSCy Schubert
72*7f2fe78bSCy Schubert /*
73*7f2fe78bSCy Schubert * Return TRUE iff all the elements of critical exist in known.
74*7f2fe78bSCy Schubert */
75*7f2fe78bSCy Schubert static int
testMechAttrsKnown(gss_const_OID_set critical,gss_const_OID_set known)76*7f2fe78bSCy Schubert testMechAttrsKnown(gss_const_OID_set critical,
77*7f2fe78bSCy Schubert gss_const_OID_set known)
78*7f2fe78bSCy Schubert {
79*7f2fe78bSCy Schubert size_t i;
80*7f2fe78bSCy Schubert
81*7f2fe78bSCy Schubert if (critical != GSS_C_NO_OID_SET) {
82*7f2fe78bSCy Schubert for (i = 0; i < critical->count; i++) {
83*7f2fe78bSCy Schubert if (!testMechAttr(&critical->elements[i], known))
84*7f2fe78bSCy Schubert return 0;
85*7f2fe78bSCy Schubert }
86*7f2fe78bSCy Schubert }
87*7f2fe78bSCy Schubert
88*7f2fe78bSCy Schubert return 1;
89*7f2fe78bSCy Schubert }
90*7f2fe78bSCy Schubert
91*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_indicate_mechs_by_attrs(OM_uint32 * minor,gss_const_OID_set desired_mech_attrs,gss_const_OID_set except_mech_attrs,gss_const_OID_set critical_mech_attrs,gss_OID_set * mechs)92*7f2fe78bSCy Schubert gss_indicate_mechs_by_attrs(
93*7f2fe78bSCy Schubert OM_uint32 *minor,
94*7f2fe78bSCy Schubert gss_const_OID_set desired_mech_attrs,
95*7f2fe78bSCy Schubert gss_const_OID_set except_mech_attrs,
96*7f2fe78bSCy Schubert gss_const_OID_set critical_mech_attrs,
97*7f2fe78bSCy Schubert gss_OID_set *mechs)
98*7f2fe78bSCy Schubert {
99*7f2fe78bSCy Schubert OM_uint32 status, tmpMinor;
100*7f2fe78bSCy Schubert gss_OID_set allMechs = GSS_C_NO_OID_SET;
101*7f2fe78bSCy Schubert size_t i;
102*7f2fe78bSCy Schubert
103*7f2fe78bSCy Schubert if (minor != NULL)
104*7f2fe78bSCy Schubert *minor = 0;
105*7f2fe78bSCy Schubert
106*7f2fe78bSCy Schubert if (mechs != NULL)
107*7f2fe78bSCy Schubert *mechs = GSS_C_NO_OID_SET;
108*7f2fe78bSCy Schubert
109*7f2fe78bSCy Schubert if (minor == NULL || mechs == NULL)
110*7f2fe78bSCy Schubert return GSS_S_CALL_INACCESSIBLE_WRITE;
111*7f2fe78bSCy Schubert
112*7f2fe78bSCy Schubert status = gss_indicate_mechs(minor, &allMechs);
113*7f2fe78bSCy Schubert if (GSS_ERROR(status))
114*7f2fe78bSCy Schubert goto cleanup;
115*7f2fe78bSCy Schubert
116*7f2fe78bSCy Schubert status = generic_gss_create_empty_oid_set(minor, mechs);
117*7f2fe78bSCy Schubert if (GSS_ERROR(status))
118*7f2fe78bSCy Schubert goto cleanup;
119*7f2fe78bSCy Schubert
120*7f2fe78bSCy Schubert for (i = 0; i < allMechs->count; i++) {
121*7f2fe78bSCy Schubert gss_OID_set supportedAttrs = GSS_C_NO_OID_SET;
122*7f2fe78bSCy Schubert gss_OID_set knownAttrs = GSS_C_NO_OID_SET;
123*7f2fe78bSCy Schubert
124*7f2fe78bSCy Schubert status = gss_inquire_attrs_for_mech(minor, &allMechs->elements[i],
125*7f2fe78bSCy Schubert &supportedAttrs, &knownAttrs);
126*7f2fe78bSCy Schubert if (GSS_ERROR(status))
127*7f2fe78bSCy Schubert continue;
128*7f2fe78bSCy Schubert
129*7f2fe78bSCy Schubert if (testMechAttrsOffered(desired_mech_attrs,
130*7f2fe78bSCy Schubert except_mech_attrs, supportedAttrs) &&
131*7f2fe78bSCy Schubert testMechAttrsKnown(critical_mech_attrs, knownAttrs)) {
132*7f2fe78bSCy Schubert status = gss_add_oid_set_member(minor, &allMechs->elements[i],
133*7f2fe78bSCy Schubert mechs);
134*7f2fe78bSCy Schubert if (GSS_ERROR(status)) {
135*7f2fe78bSCy Schubert gss_release_oid_set(&tmpMinor, &supportedAttrs);
136*7f2fe78bSCy Schubert gss_release_oid_set(&tmpMinor, &knownAttrs);
137*7f2fe78bSCy Schubert goto cleanup;
138*7f2fe78bSCy Schubert }
139*7f2fe78bSCy Schubert }
140*7f2fe78bSCy Schubert
141*7f2fe78bSCy Schubert gss_release_oid_set(&tmpMinor, &supportedAttrs);
142*7f2fe78bSCy Schubert gss_release_oid_set(&tmpMinor, &knownAttrs);
143*7f2fe78bSCy Schubert }
144*7f2fe78bSCy Schubert
145*7f2fe78bSCy Schubert *minor = 0;
146*7f2fe78bSCy Schubert status = GSS_S_COMPLETE;
147*7f2fe78bSCy Schubert
148*7f2fe78bSCy Schubert cleanup:
149*7f2fe78bSCy Schubert gss_release_oid_set(&tmpMinor, &allMechs);
150*7f2fe78bSCy Schubert
151*7f2fe78bSCy Schubert return status;
152*7f2fe78bSCy Schubert }
153*7f2fe78bSCy Schubert
154*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_inquire_attrs_for_mech(OM_uint32 * minor,gss_const_OID mech_oid,gss_OID_set * mech_attrs,gss_OID_set * known_mech_attrs)155*7f2fe78bSCy Schubert gss_inquire_attrs_for_mech(
156*7f2fe78bSCy Schubert OM_uint32 *minor,
157*7f2fe78bSCy Schubert gss_const_OID mech_oid,
158*7f2fe78bSCy Schubert gss_OID_set *mech_attrs,
159*7f2fe78bSCy Schubert gss_OID_set *known_mech_attrs)
160*7f2fe78bSCy Schubert {
161*7f2fe78bSCy Schubert OM_uint32 status, tmpMinor;
162*7f2fe78bSCy Schubert gss_OID selected_mech, public_mech;
163*7f2fe78bSCy Schubert gss_mechanism mech;
164*7f2fe78bSCy Schubert
165*7f2fe78bSCy Schubert if (minor != NULL)
166*7f2fe78bSCy Schubert *minor = 0;
167*7f2fe78bSCy Schubert
168*7f2fe78bSCy Schubert if (mech_attrs != NULL)
169*7f2fe78bSCy Schubert *mech_attrs = GSS_C_NO_OID_SET;
170*7f2fe78bSCy Schubert
171*7f2fe78bSCy Schubert if (known_mech_attrs != NULL)
172*7f2fe78bSCy Schubert *known_mech_attrs = GSS_C_NO_OID_SET;
173*7f2fe78bSCy Schubert
174*7f2fe78bSCy Schubert if (minor == NULL)
175*7f2fe78bSCy Schubert return GSS_S_CALL_INACCESSIBLE_WRITE;
176*7f2fe78bSCy Schubert
177*7f2fe78bSCy Schubert status = gssint_select_mech_type(minor, mech_oid, &selected_mech);
178*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
179*7f2fe78bSCy Schubert return status;
180*7f2fe78bSCy Schubert
181*7f2fe78bSCy Schubert mech = gssint_get_mechanism(selected_mech);
182*7f2fe78bSCy Schubert if (mech == NULL)
183*7f2fe78bSCy Schubert return GSS_S_BAD_MECH;
184*7f2fe78bSCy Schubert
185*7f2fe78bSCy Schubert /* If the mech does not implement RFC 5587, return success with an empty
186*7f2fe78bSCy Schubert * mech_attrs and known_mech_attrs. */
187*7f2fe78bSCy Schubert if (mech->gss_inquire_attrs_for_mech == NULL)
188*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
189*7f2fe78bSCy Schubert
190*7f2fe78bSCy Schubert public_mech = gssint_get_public_oid(selected_mech);
191*7f2fe78bSCy Schubert status = mech->gss_inquire_attrs_for_mech(minor, public_mech, mech_attrs,
192*7f2fe78bSCy Schubert known_mech_attrs);
193*7f2fe78bSCy Schubert if (GSS_ERROR(status)) {
194*7f2fe78bSCy Schubert map_error(minor, mech);
195*7f2fe78bSCy Schubert return status;
196*7f2fe78bSCy Schubert }
197*7f2fe78bSCy Schubert
198*7f2fe78bSCy Schubert if (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) {
199*7f2fe78bSCy Schubert status = generic_gss_copy_oid_set(minor,
200*7f2fe78bSCy Schubert gss_ma_known_attrs,
201*7f2fe78bSCy Schubert known_mech_attrs);
202*7f2fe78bSCy Schubert if (GSS_ERROR(status)) {
203*7f2fe78bSCy Schubert gss_release_oid_set(&tmpMinor, mech_attrs);
204*7f2fe78bSCy Schubert if (mech_attrs != NULL)
205*7f2fe78bSCy Schubert *mech_attrs = GSS_C_NO_OID_SET;
206*7f2fe78bSCy Schubert }
207*7f2fe78bSCy Schubert }
208*7f2fe78bSCy Schubert
209*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
210*7f2fe78bSCy Schubert }
211*7f2fe78bSCy Schubert
212*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_display_mech_attr(OM_uint32 * minor,gss_const_OID mech_attr,gss_buffer_t name,gss_buffer_t short_desc,gss_buffer_t long_desc)213*7f2fe78bSCy Schubert gss_display_mech_attr(
214*7f2fe78bSCy Schubert OM_uint32 *minor,
215*7f2fe78bSCy Schubert gss_const_OID mech_attr,
216*7f2fe78bSCy Schubert gss_buffer_t name,
217*7f2fe78bSCy Schubert gss_buffer_t short_desc,
218*7f2fe78bSCy Schubert gss_buffer_t long_desc)
219*7f2fe78bSCy Schubert {
220*7f2fe78bSCy Schubert return generic_gss_display_mech_attr(minor, mech_attr,
221*7f2fe78bSCy Schubert name, short_desc, long_desc);
222*7f2fe78bSCy Schubert }
223