2 * Copyright (c) 2010 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "mech_locl.h"
39 get_option_def(int def
, gss_const_OID mech
, gss_mo_desc
*mo
, gss_buffer_t value
)
46 _gss_mo_get_option_1(gss_const_OID mech
, gss_mo_desc
*mo
, gss_buffer_t value
)
48 return get_option_def(1, mech
, mo
, value
);
52 _gss_mo_get_option_0(gss_const_OID mech
, gss_mo_desc
*mo
, gss_buffer_t value
)
54 return get_option_def(0, mech
, mo
, value
);
58 _gss_mo_get_ctx_as_string(gss_const_OID mech
, gss_mo_desc
*mo
, gss_buffer_t value
)
61 value
->value
= strdup((char *)mo
->ctx
);
62 if (value
->value
== NULL
)
64 value
->length
= strlen((char *)mo
->ctx
);
69 GSSAPI_LIB_FUNCTION
int GSSAPI_LIB_CALL
70 gss_mo_set(gss_const_OID mech
, gss_const_OID option
,
71 int enable
, gss_buffer_t value
)
73 gssapi_mech_interface m
;
76 if ((m
= __gss_get_mechanism(mech
)) == NULL
)
77 return GSS_S_BAD_MECH
;
79 for (n
= 0; n
< m
->gm_mo_num
; n
++)
80 if (gss_oid_equal(option
, m
->gm_mo
[n
].option
) && m
->gm_mo
[n
].set
)
81 return m
->gm_mo
[n
].set(mech
, &m
->gm_mo
[n
], enable
, value
);
85 GSSAPI_LIB_FUNCTION
int GSSAPI_LIB_CALL
86 gss_mo_get(gss_const_OID mech
, gss_const_OID option
, gss_buffer_t value
)
88 gssapi_mech_interface m
;
91 _mg_buffer_zero(value
);
93 if ((m
= __gss_get_mechanism(mech
)) == NULL
)
96 for (n
= 0; n
< m
->gm_mo_num
; n
++)
97 if (gss_oid_equal(option
, m
->gm_mo
[n
].option
) && m
->gm_mo
[n
].get
)
98 return m
->gm_mo
[n
].get(mech
, &m
->gm_mo
[n
], value
);
104 add_all_mo(gssapi_mech_interface m
, gss_OID_set
*options
, OM_uint32 mask
)
109 for (n
= 0; n
< m
->gm_mo_num
; n
++)
110 if ((m
->gm_mo
[n
].flags
& mask
) == mask
)
111 gss_add_oid_set_member(&minor
, m
->gm_mo
[n
].option
, options
);
114 GSSAPI_LIB_FUNCTION
void GSSAPI_LIB_CALL
115 gss_mo_list(gss_const_OID mech
, gss_OID_set
*options
)
117 gssapi_mech_interface m
;
118 OM_uint32 major
, minor
;
123 *options
= GSS_C_NO_OID_SET
;
125 if ((m
= __gss_get_mechanism(mech
)) == NULL
)
128 major
= gss_create_empty_oid_set(&minor
, options
);
129 if (major
!= GSS_S_COMPLETE
)
132 add_all_mo(m
, options
, 0);
135 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
136 gss_mo_name(gss_const_OID mech
, gss_const_OID option
, gss_buffer_t name
)
138 gssapi_mech_interface m
;
142 return GSS_S_BAD_NAME
;
144 if ((m
= __gss_get_mechanism(mech
)) == NULL
)
145 return GSS_S_BAD_MECH
;
147 for (n
= 0; n
< m
->gm_mo_num
; n
++) {
148 if (gss_oid_equal(option
, m
->gm_mo
[n
].option
)) {
150 * If ther is no name, its because its a GSS_C_MA and there is already a table for that.
152 if (m
->gm_mo
[n
].name
) {
153 name
->value
= strdup(m
->gm_mo
[n
].name
);
154 if (name
->value
== NULL
)
155 return GSS_S_BAD_NAME
;
156 name
->length
= strlen(m
->gm_mo
[n
].name
);
157 return GSS_S_COMPLETE
;
160 return gss_display_mech_attr(&junk
, option
,
165 return GSS_S_BAD_NAME
;
169 * Helper function to allow NULL name
173 mo_value(const gss_const_OID mech
, gss_const_OID option
, gss_buffer_t name
)
176 return GSS_S_COMPLETE
;
178 if (gss_mo_get(mech
, option
, name
) != 0 && name
->length
== 0)
179 return GSS_S_FAILURE
;
181 return GSS_S_COMPLETE
;
185 * Returns differnt protocol names and description of the mechanism.
187 * @param minor_status minor status code
188 * @param desired_mech mech list query
189 * @param sasl_mech_name SASL GS2 protocol name
190 * @param mech_name gssapi protocol name
191 * @param mech_description description of gssapi mech
193 * @return returns GSS_S_COMPLETE or a error code.
198 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
199 gss_inquire_saslname_for_mech(OM_uint32
*minor_status
,
200 const gss_OID desired_mech
,
201 gss_buffer_t sasl_mech_name
,
202 gss_buffer_t mech_name
,
203 gss_buffer_t mech_description
)
207 _mg_buffer_zero(sasl_mech_name
);
208 _mg_buffer_zero(mech_name
);
209 _mg_buffer_zero(mech_description
);
214 if (desired_mech
== NULL
)
215 return GSS_S_BAD_MECH
;
217 major
= mo_value(desired_mech
, GSS_C_MA_SASL_MECH_NAME
, sasl_mech_name
);
218 if (major
) return major
;
220 major
= mo_value(desired_mech
, GSS_C_MA_MECH_NAME
, mech_name
);
221 if (major
) return major
;
223 major
= mo_value(desired_mech
, GSS_C_MA_MECH_DESCRIPTION
, mech_description
);
224 if (major
) return major
;
226 return GSS_S_COMPLETE
;
230 * Find a mech for a sasl name
232 * @param minor_status minor status code
233 * @param sasl_mech_name
236 * @return returns GSS_S_COMPLETE or an error code.
239 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
240 gss_inquire_mech_for_saslname(OM_uint32
*minor_status
,
241 const gss_buffer_t sasl_mech_name
,
244 struct _gss_mech_switch
*m
;
245 gss_buffer_desc name
;
252 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
254 major
= mo_value(&m
->gm_mech_oid
, GSS_C_MA_SASL_MECH_NAME
, &name
);
257 if (name
.length
== sasl_mech_name
->length
&&
258 memcmp(name
.value
, sasl_mech_name
->value
, name
.length
) == 0) {
259 gss_release_buffer(&major
, &name
);
260 *mech_type
= &m
->gm_mech_oid
;
263 gss_release_buffer(&major
, &name
);
266 return GSS_S_BAD_MECH
;
270 * Return set of mechanism that fullfill the criteria
272 * @param minor_status minor status code
273 * @param desired_mech_attrs
274 * @param except_mech_attrs
275 * @param critical_mech_attrs
276 * @param mechs returned mechs, free with gss_release_oid_set().
278 * @return returns GSS_S_COMPLETE or an error code.
281 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
282 gss_indicate_mechs_by_attrs(OM_uint32
* minor_status
,
283 gss_const_OID_set desired_mech_attrs
,
284 gss_const_OID_set except_mech_attrs
,
285 gss_const_OID_set critical_mech_attrs
,
288 struct _gss_mech_switch
*ms
;
292 major
= gss_create_empty_oid_set(minor_status
, mechs
);
298 HEIM_SLIST_FOREACH(ms
, &_gss_mechs
, gm_link
) {
299 gssapi_mech_interface mi
= &ms
->gm_mech
;
301 if (desired_mech_attrs
) {
302 for (n
= 0; n
< desired_mech_attrs
->count
; n
++) {
303 for (m
= 0; m
< mi
->gm_mo_num
; m
++)
304 if (gss_oid_equal(mi
->gm_mo
[m
].option
, &desired_mech_attrs
->elements
[n
]))
306 if (m
== mi
->gm_mo_num
)
311 if (except_mech_attrs
) {
312 for (n
= 0; n
< desired_mech_attrs
->count
; n
++) {
313 for (m
= 0; m
< mi
->gm_mo_num
; m
++) {
314 if (gss_oid_equal(mi
->gm_mo
[m
].option
, &desired_mech_attrs
->elements
[n
]))
320 if (critical_mech_attrs
) {
321 for (n
= 0; n
< desired_mech_attrs
->count
; n
++) {
322 for (m
= 0; m
< mi
->gm_mo_num
; m
++) {
323 if (mi
->gm_mo
[m
].flags
& GSS_MO_MA_CRITICAL
)
325 if (gss_oid_equal(mi
->gm_mo
[m
].option
, &desired_mech_attrs
->elements
[n
]))
328 if (m
== mi
->gm_mo_num
)
339 return GSS_S_FAILURE
;
343 * List support attributes for a mech and/or all mechanisms.
345 * @param minor_status minor status code
346 * @param mech given together with mech_attr will return the list of
347 * attributes for mechanism, can optionally be GSS_C_NO_OID.
348 * @param mech_attr see mech parameter, can optionally be NULL,
349 * release with gss_release_oid_set().
350 * @param known_mech_attrs all attributes for mechanisms supported,
351 * release with gss_release_oid_set().
356 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
357 gss_inquire_attrs_for_mech(OM_uint32
* minor_status
,
359 gss_OID_set
*mech_attr
,
360 gss_OID_set
*known_mech_attrs
)
362 OM_uint32 major
, junk
;
364 if (mech_attr
&& mech
) {
365 gssapi_mech_interface m
;
367 if ((m
= __gss_get_mechanism(mech
)) == NULL
) {
369 return GSS_S_BAD_MECH
;
372 major
= gss_create_empty_oid_set(minor_status
, mech_attr
);
373 if (major
!= GSS_S_COMPLETE
)
376 add_all_mo(m
, mech_attr
, GSS_MO_MA
);
379 if (known_mech_attrs
) {
380 struct _gss_mech_switch
*m
;
382 major
= gss_create_empty_oid_set(minor_status
, known_mech_attrs
);
385 gss_release_oid_set(&junk
, mech_attr
);
391 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
)
392 add_all_mo(&m
->gm_mech
, known_mech_attrs
, GSS_MO_MA
);
396 return GSS_S_COMPLETE
;
400 * Return names and descriptions of mech attributes
402 * @param minor_status minor status code
408 * @return returns GSS_S_COMPLETE or an error code.
411 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
412 gss_display_mech_attr(OM_uint32
* minor_status
,
413 gss_const_OID mech_attr
,
415 gss_buffer_t short_desc
,
416 gss_buffer_t long_desc
)
418 struct _gss_oid_name_table
*ma
= NULL
;
422 _mg_buffer_zero(name
);
423 _mg_buffer_zero(short_desc
);
424 _mg_buffer_zero(long_desc
);
429 for (n
= 0; ma
== NULL
&& _gss_ont_ma
[n
].oid
; n
++)
430 if (gss_oid_equal(mech_attr
, _gss_ont_ma
[n
].oid
))
431 ma
= &_gss_ont_ma
[n
];
434 return GSS_S_BAD_MECH_ATTR
;
438 n
.value
= rk_UNCONST(ma
->name
);
439 n
.length
= strlen(ma
->name
);
440 major
= _gss_copy_buffer(minor_status
, &n
, name
);
441 if (major
!= GSS_S_COMPLETE
)
447 n
.value
= rk_UNCONST(ma
->short_desc
);
448 n
.length
= strlen(ma
->short_desc
);
449 major
= _gss_copy_buffer(minor_status
, &n
, short_desc
);
450 if (major
!= GSS_S_COMPLETE
)
456 n
.value
= rk_UNCONST(ma
->long_desc
);
457 n
.length
= strlen(ma
->long_desc
);
458 major
= _gss_copy_buffer(minor_status
, &n
, long_desc
);
459 if (major
!= GSS_S_COMPLETE
)
463 return GSS_S_COMPLETE
;