xref: /minix3/crypto/external/bsd/heimdal/dist/lib/gssapi/mech/gss_mo.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1 /*	$NetBSD: gss_mo.c,v 1.1.1.1 2011/04/13 18:14:46 elric Exp $	*/
2 
3 /*
4  * Copyright (c) 2010 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * 3. Neither the name of the Institute nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include "mech_locl.h"
39 
40 static int
41 get_option_def(int def, gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
42 {
43     return def;
44 }
45 
46 
47 int
48 _gss_mo_get_option_1(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
49 {
50     return get_option_def(1, mech, mo, value);
51 }
52 
53 int
54 _gss_mo_get_option_0(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
55 {
56     return get_option_def(0, mech, mo, value);
57 }
58 
59 int
60 _gss_mo_get_ctx_as_string(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
61 {
62     if (value) {
63 	value->value = strdup((char *)mo->ctx);
64 	if (value->value == NULL)
65 	    return 1;
66 	value->length = strlen((char *)mo->ctx);
67     }
68     return 0;
69 }
70 
71 GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL
72 gss_mo_set(gss_const_OID mech, gss_const_OID option,
73 	   int enable, gss_buffer_t value)
74 {
75     gssapi_mech_interface m;
76     size_t n;
77 
78     if ((m = __gss_get_mechanism(mech)) == NULL)
79 	return GSS_S_BAD_MECH;
80 
81     for (n = 0; n < m->gm_mo_num; n++)
82 	if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].set)
83 	    return m->gm_mo[n].set(mech, &m->gm_mo[n], enable, value);
84     return 0;
85 }
86 
87 GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL
88 gss_mo_get(gss_const_OID mech, gss_const_OID option, gss_buffer_t value)
89 {
90     gssapi_mech_interface m;
91     size_t n;
92 
93     _mg_buffer_zero(value);
94 
95     if ((m = __gss_get_mechanism(mech)) == NULL)
96 	return 0;
97 
98     for (n = 0; n < m->gm_mo_num; n++)
99 	if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].get)
100 	    return m->gm_mo[n].get(mech, &m->gm_mo[n], value);
101 
102     return 0;
103 }
104 
105 static void
106 add_all_mo(gssapi_mech_interface m, gss_OID_set *options, OM_uint32 mask)
107 {
108     OM_uint32 minor;
109     size_t n;
110 
111     for (n = 0; n < m->gm_mo_num; n++)
112 	if ((m->gm_mo[n].flags & mask) == mask)
113 	    gss_add_oid_set_member(&minor, m->gm_mo[n].option, options);
114 }
115 
116 GSSAPI_LIB_FUNCTION void GSSAPI_LIB_CALL
117 gss_mo_list(gss_const_OID mech, gss_OID_set *options)
118 {
119     gssapi_mech_interface m;
120     OM_uint32 major, minor;
121 
122     if (options == NULL)
123 	return;
124 
125     *options = GSS_C_NO_OID_SET;
126 
127     if ((m = __gss_get_mechanism(mech)) == NULL)
128 	return;
129 
130     major = gss_create_empty_oid_set(&minor, options);
131     if (major != GSS_S_COMPLETE)
132 	return;
133 
134     add_all_mo(m, options, 0);
135 }
136 
137 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
138 gss_mo_name(gss_const_OID mech, gss_const_OID option, gss_buffer_t name)
139 {
140     gssapi_mech_interface m;
141     size_t n;
142 
143     if (name == NULL)
144 	return GSS_S_BAD_NAME;
145 
146     if ((m = __gss_get_mechanism(mech)) == NULL)
147 	return GSS_S_BAD_MECH;
148 
149     for (n = 0; n < m->gm_mo_num; n++) {
150 	if (gss_oid_equal(option, m->gm_mo[n].option)) {
151 	    /*
152 	     * If ther is no name, its because its a GSS_C_MA and there is already a table for that.
153 	     */
154 	    if (m->gm_mo[n].name) {
155 		name->value = strdup(m->gm_mo[n].name);
156 		if (name->value == NULL)
157 		    return GSS_S_BAD_NAME;
158 		name->length = strlen(m->gm_mo[n].name);
159 		return GSS_S_COMPLETE;
160 	    } else {
161 		OM_uint32 junk;
162 		return gss_display_mech_attr(&junk, option,
163 					     NULL, name, NULL);
164 	    }
165 	}
166     }
167     return GSS_S_BAD_NAME;
168 }
169 
170 /*
171  * Helper function to allow NULL name
172  */
173 
174 static OM_uint32
175 mo_value(const gss_const_OID mech, gss_const_OID option, gss_buffer_t name)
176 {
177     if (name == NULL)
178 	return GSS_S_COMPLETE;
179 
180     if (gss_mo_get(mech, option, name) != 0 && name->length == 0)
181 	return GSS_S_FAILURE;
182 
183     return GSS_S_COMPLETE;
184 }
185 
186 /**
187  * Returns differnt protocol names and description of the mechanism.
188  *
189  * @param minor_status minor status code
190  * @param desired_mech mech list query
191  * @param sasl_mech_name SASL GS2 protocol name
192  * @param mech_name gssapi protocol name
193  * @param mech_description description of gssapi mech
194  *
195  * @return returns GSS_S_COMPLETE or a error code.
196  *
197  * @ingroup gssapi
198  */
199 
200 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
201 gss_inquire_saslname_for_mech(OM_uint32 *minor_status,
202 			      const gss_OID desired_mech,
203 			      gss_buffer_t sasl_mech_name,
204 			      gss_buffer_t mech_name,
205 			      gss_buffer_t mech_description)
206 {
207     OM_uint32 major;
208 
209     _mg_buffer_zero(sasl_mech_name);
210     _mg_buffer_zero(mech_name);
211     _mg_buffer_zero(mech_description);
212 
213     if (minor_status)
214 	*minor_status = 0;
215 
216     if (desired_mech == NULL)
217 	return GSS_S_BAD_MECH;
218 
219     major = mo_value(desired_mech, GSS_C_MA_SASL_MECH_NAME, sasl_mech_name);
220     if (major) return major;
221 
222     major = mo_value(desired_mech, GSS_C_MA_MECH_NAME, mech_name);
223     if (major) return major;
224 
225     major = mo_value(desired_mech, GSS_C_MA_MECH_DESCRIPTION, mech_description);
226     if (major) return major;
227 
228     return GSS_S_COMPLETE;
229 }
230 
231 /**
232  * Find a mech for a sasl name
233  *
234  * @param minor_status minor status code
235  * @param sasl_mech_name
236  * @param mech_type
237  *
238  * @return returns GSS_S_COMPLETE or an error code.
239  */
240 
241 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
242 gss_inquire_mech_for_saslname(OM_uint32 *minor_status,
243 			      const gss_buffer_t sasl_mech_name,
244 			      gss_OID *mech_type)
245 {
246     struct _gss_mech_switch *m;
247     gss_buffer_desc name;
248     OM_uint32 major;
249 
250     _gss_load_mech();
251 
252     *mech_type = NULL;
253 
254     HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
255 
256 	major = mo_value(&m->gm_mech_oid, GSS_C_MA_SASL_MECH_NAME, &name);
257 	if (major)
258 	    continue;
259 	if (name.length == sasl_mech_name->length &&
260 	    memcmp(name.value, sasl_mech_name->value, name.length) == 0) {
261 	    gss_release_buffer(&major, &name);
262 	    *mech_type = &m->gm_mech_oid;
263 	    return 0;
264 	}
265 	gss_release_buffer(&major, &name);
266     }
267 
268     return GSS_S_BAD_MECH;
269 }
270 
271 /**
272  * Return set of mechanism that fullfill the criteria
273  *
274  * @param minor_status minor status code
275  * @param desired_mech_attrs
276  * @param except_mech_attrs
277  * @param critical_mech_attrs
278  * @param mechs returned mechs, free with gss_release_oid_set().
279  *
280  * @return returns GSS_S_COMPLETE or an error code.
281  */
282 
283 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
284 gss_indicate_mechs_by_attrs(OM_uint32 * minor_status,
285 			    gss_const_OID_set desired_mech_attrs,
286 			    gss_const_OID_set except_mech_attrs,
287 			    gss_const_OID_set critical_mech_attrs,
288 			    gss_OID_set *mechs)
289 {
290     struct _gss_mech_switch *ms;
291     OM_uint32 major;
292     size_t n, m;
293 
294     major = gss_create_empty_oid_set(minor_status, mechs);
295     if (major)
296 	return major;
297 
298     _gss_load_mech();
299 
300     HEIM_SLIST_FOREACH(ms, &_gss_mechs, gm_link) {
301 	gssapi_mech_interface mi = &ms->gm_mech;
302 
303 	if (desired_mech_attrs) {
304 	    for (n = 0; n < desired_mech_attrs->count; n++) {
305 		for (m = 0; m < mi->gm_mo_num; m++)
306 		    if (gss_oid_equal(mi->gm_mo[m].option, &desired_mech_attrs->elements[n]))
307 			break;
308 		if (m == mi->gm_mo_num)
309 		    goto next;
310 	    }
311 	}
312 
313 	if (except_mech_attrs) {
314 	    for (n = 0; n < desired_mech_attrs->count; n++) {
315 		for (m = 0; m < mi->gm_mo_num; m++) {
316 		    if (gss_oid_equal(mi->gm_mo[m].option, &desired_mech_attrs->elements[n]))
317 			goto next;
318 		}
319 	    }
320 	}
321 
322 	if (critical_mech_attrs) {
323 	    for (n = 0; n < desired_mech_attrs->count; n++) {
324 		for (m = 0; m < mi->gm_mo_num; m++) {
325 		    if (mi->gm_mo[m].flags & GSS_MO_MA_CRITICAL)
326 			continue;
327 		    if (gss_oid_equal(mi->gm_mo[m].option, &desired_mech_attrs->elements[n]))
328 			break;
329 		}
330 		if (m == mi->gm_mo_num)
331 		    goto next;
332 	    }
333 	}
334 
335 
336     next:
337 	do { } while(0);
338     }
339 
340 
341     return GSS_S_FAILURE;
342 }
343 
344 /**
345  * List support attributes for a mech and/or all mechanisms.
346  *
347  * @param minor_status minor status code
348  * @param mech given together with mech_attr will return the list of
349  *        attributes for mechanism, can optionally be GSS_C_NO_OID.
350  * @param mech_attr see mech parameter, can optionally be NULL,
351  *        release with gss_release_oid_set().
352  * @param known_mech_attrs all attributes for mechanisms supported,
353  *        release with gss_release_oid_set().
354  *
355  * @ingroup gssapi
356  */
357 
358 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
359 gss_inquire_attrs_for_mech(OM_uint32 * minor_status,
360 			   gss_const_OID mech,
361 			   gss_OID_set *mech_attr,
362 			   gss_OID_set *known_mech_attrs)
363 {
364     OM_uint32 major, junk;
365 
366     if (mech_attr && mech) {
367 	gssapi_mech_interface m;
368 
369 	if ((m = __gss_get_mechanism(mech)) == NULL) {
370 	    *minor_status = 0;
371 	    return GSS_S_BAD_MECH;
372 	}
373 
374 	major = gss_create_empty_oid_set(minor_status, mech_attr);
375 	if (major != GSS_S_COMPLETE)
376 	    return major;
377 
378 	add_all_mo(m, mech_attr, GSS_MO_MA);
379     }
380 
381     if (known_mech_attrs) {
382 	struct _gss_mech_switch *m;
383 
384 	major = gss_create_empty_oid_set(minor_status, known_mech_attrs);
385 	if (major) {
386 	    if (mech_attr)
387 		gss_release_oid_set(&junk, mech_attr);
388 	    return major;
389 	}
390 
391 	_gss_load_mech();
392 
393 	HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link)
394 	    add_all_mo(&m->gm_mech, known_mech_attrs, GSS_MO_MA);
395     }
396 
397 
398     return GSS_S_COMPLETE;
399 }
400 
401 /**
402  * Return names and descriptions of mech attributes
403  *
404  * @param minor_status minor status code
405  * @param mech_attr
406  * @param name
407  * @param short_desc
408  * @param long_desc
409  *
410  * @return returns GSS_S_COMPLETE or an error code.
411  */
412 
413 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
414 gss_display_mech_attr(OM_uint32 * minor_status,
415 		      gss_const_OID mech_attr,
416 		      gss_buffer_t name,
417 		      gss_buffer_t short_desc,
418 		      gss_buffer_t long_desc)
419 {
420     struct _gss_oid_name_table *ma = NULL;
421     OM_uint32 major;
422     size_t n;
423 
424     _mg_buffer_zero(name);
425     _mg_buffer_zero(short_desc);
426     _mg_buffer_zero(long_desc);
427 
428     if (minor_status)
429 	*minor_status = 0;
430 
431     for (n = 0; ma == NULL && _gss_ont_ma[n].oid; n++)
432 	if (gss_oid_equal(mech_attr, _gss_ont_ma[n].oid))
433 	    ma = &_gss_ont_ma[n];
434 
435     if (ma == NULL)
436 	return GSS_S_BAD_MECH_ATTR;
437 
438     if (name) {
439 	gss_buffer_desc n;
440 	n.value = rk_UNCONST(ma->name);
441 	n.length = strlen(ma->name);
442 	major = _gss_copy_buffer(minor_status, &n, name);
443 	if (major != GSS_S_COMPLETE)
444 	    return major;
445     }
446 
447     if (short_desc) {
448 	gss_buffer_desc n;
449 	n.value = rk_UNCONST(ma->short_desc);
450 	n.length = strlen(ma->short_desc);
451 	major = _gss_copy_buffer(minor_status, &n, short_desc);
452 	if (major != GSS_S_COMPLETE)
453 	    return major;
454     }
455 
456     if (long_desc) {
457 	gss_buffer_desc n;
458 	n.value = rk_UNCONST(ma->long_desc);
459 	n.length = strlen(ma->long_desc);
460 	major = _gss_copy_buffer(minor_status, &n, long_desc);
461 	if (major != GSS_S_COMPLETE)
462 	    return major;
463     }
464 
465     return GSS_S_COMPLETE;
466 }
467