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