Line data Source code
1 : /*
2 : * Copyright (c) 2010 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
7 : * Portions Copyright (c) 2010 PADL Software Pty Ltd. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in the
18 : * documentation and/or other materials provided with the distribution.
19 : *
20 : * 3. Neither the name of the Institute nor the names of its contributors
21 : * may be used to endorse or promote products derived from this software
22 : * without specific prior written permission.
23 : *
24 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
25 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
28 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 : * SUCH DAMAGE.
35 : */
36 :
37 : #include "mech_locl.h"
38 :
39 : #include <crypto-headers.h>
40 :
41 : static int
42 0 : get_option_def(int def, gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
43 : {
44 0 : return def;
45 : }
46 :
47 : int
48 0 : _gss_mo_get_option_1(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
49 : {
50 0 : return get_option_def(1, mech, mo, value);
51 : }
52 :
53 : int
54 0 : _gss_mo_get_option_0(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
55 : {
56 0 : return get_option_def(0, mech, mo, value);
57 : }
58 :
59 : int
60 0 : _gss_mo_get_ctx_as_string(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value)
61 : {
62 0 : if (value) {
63 0 : value->value = strdup((char *)mo->ctx);
64 0 : if (value->value == NULL)
65 0 : return GSS_S_FAILURE;
66 0 : value->length = strlen((char *)mo->ctx);
67 : }
68 0 : return GSS_S_COMPLETE;
69 : }
70 :
71 : GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL
72 0 : gss_mo_set(gss_const_OID mech, gss_const_OID option,
73 : int enable, gss_buffer_t value)
74 : {
75 0 : gssapi_mech_interface m;
76 0 : size_t n;
77 :
78 0 : if ((m = __gss_get_mechanism(mech)) == NULL)
79 0 : return GSS_S_BAD_MECH;
80 :
81 0 : for (n = 0; n < m->gm_mo_num; n++)
82 0 : if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].set)
83 0 : return m->gm_mo[n].set(mech, &m->gm_mo[n], enable, value);
84 :
85 0 : return GSS_S_UNAVAILABLE;
86 : }
87 :
88 : GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL
89 0 : gss_mo_get(gss_const_OID mech, gss_const_OID option, gss_buffer_t value)
90 : {
91 0 : gssapi_mech_interface m;
92 0 : size_t n;
93 :
94 0 : _mg_buffer_zero(value);
95 :
96 0 : if ((m = __gss_get_mechanism(mech)) == NULL)
97 0 : return GSS_S_BAD_MECH;
98 :
99 0 : for (n = 0; n < m->gm_mo_num; n++)
100 0 : if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].get)
101 0 : return m->gm_mo[n].get(mech, &m->gm_mo[n], value);
102 :
103 0 : return GSS_S_UNAVAILABLE;
104 : }
105 :
106 : static void
107 0 : add_all_mo(gssapi_mech_interface m, gss_OID_set *options, OM_uint32 mask)
108 : {
109 0 : OM_uint32 minor;
110 0 : size_t n;
111 :
112 0 : for (n = 0; n < m->gm_mo_num; n++)
113 0 : if ((m->gm_mo[n].flags & mask) == mask)
114 0 : gss_add_oid_set_member(&minor, m->gm_mo[n].option, options);
115 0 : }
116 :
117 : GSSAPI_LIB_FUNCTION void GSSAPI_LIB_CALL
118 0 : gss_mo_list(gss_const_OID mech, gss_OID_set *options)
119 : {
120 0 : gssapi_mech_interface m;
121 0 : OM_uint32 major, minor;
122 :
123 0 : if (options == NULL)
124 0 : return;
125 :
126 0 : *options = GSS_C_NO_OID_SET;
127 :
128 0 : if ((m = __gss_get_mechanism(mech)) == NULL)
129 0 : return;
130 :
131 0 : major = gss_create_empty_oid_set(&minor, options);
132 0 : if (major != GSS_S_COMPLETE)
133 0 : return;
134 :
135 0 : add_all_mo(m, options, 0);
136 : }
137 :
138 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
139 0 : gss_mo_name(gss_const_OID mech, gss_const_OID option, gss_buffer_t name)
140 : {
141 0 : gssapi_mech_interface m;
142 0 : size_t n;
143 :
144 0 : if (name == NULL)
145 0 : return GSS_S_BAD_NAME;
146 :
147 0 : if ((m = __gss_get_mechanism(mech)) == NULL)
148 0 : return GSS_S_BAD_MECH;
149 :
150 0 : for (n = 0; n < m->gm_mo_num; n++) {
151 0 : if (gss_oid_equal(option, m->gm_mo[n].option)) {
152 : /*
153 : * If there is no name, its because its a GSS_C_MA and
154 : * there is already a table for that.
155 : */
156 0 : if (m->gm_mo[n].name) {
157 0 : name->value = strdup(m->gm_mo[n].name);
158 0 : if (name->value == NULL)
159 0 : return GSS_S_BAD_NAME;
160 0 : name->length = strlen(m->gm_mo[n].name);
161 0 : return GSS_S_COMPLETE;
162 : } else {
163 0 : OM_uint32 junk;
164 0 : return gss_display_mech_attr(&junk, option,
165 : NULL, name, NULL);
166 : }
167 : }
168 : }
169 0 : return GSS_S_BAD_NAME;
170 : }
171 :
172 : /*
173 : * Helper function to allow NULL name
174 : */
175 :
176 : static OM_uint32
177 0 : mo_value(const gss_const_OID mech, gss_const_OID option, gss_buffer_t name)
178 : {
179 0 : if (name == NULL)
180 0 : return GSS_S_COMPLETE;
181 :
182 0 : return gss_mo_get(mech, option, name);
183 : }
184 :
185 : /* code derived from draft-ietf-cat-sasl-gssapi-01 */
186 : static char basis_32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
187 :
188 : static OM_uint32
189 0 : make_sasl_name(OM_uint32 *minor, const gss_OID mech, char sasl_name[16])
190 : {
191 0 : EVP_MD_CTX *ctx;
192 0 : char *p = sasl_name;
193 0 : u_char hdr[2], hash[20], *h = hash;
194 :
195 0 : if (mech->length > 127)
196 0 : return GSS_S_BAD_MECH;
197 :
198 0 : hdr[0] = 0x06;
199 0 : hdr[1] = mech->length;
200 :
201 0 : ctx = EVP_MD_CTX_create();
202 0 : EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
203 0 : EVP_DigestUpdate(ctx, hdr, 2);
204 0 : EVP_DigestUpdate(ctx, mech->elements, mech->length);
205 0 : EVP_DigestFinal_ex(ctx, hash, NULL);
206 0 : EVP_MD_CTX_destroy(ctx);
207 :
208 0 : memcpy(p, "GS2-", 4);
209 0 : p += 4;
210 :
211 0 : *p++ = basis_32[(h[0] >> 3)];
212 0 : *p++ = basis_32[((h[0] & 7) << 2) | (h[1] >> 6)];
213 0 : *p++ = basis_32[(h[1] & 0x3f) >> 1];
214 0 : *p++ = basis_32[((h[1] & 1) << 4) | (h[2] >> 4)];
215 0 : *p++ = basis_32[((h[2] & 0xf) << 1) | (h[3] >> 7)];
216 0 : *p++ = basis_32[(h[3] & 0x7f) >> 2];
217 0 : *p++ = basis_32[((h[3] & 3) << 3) | (h[4] >> 5)];
218 0 : *p++ = basis_32[(h[4] & 0x1f)];
219 0 : *p++ = basis_32[(h[5] >> 3)];
220 0 : *p++ = basis_32[((h[5] & 7) << 2) | (h[6] >> 6)];
221 0 : *p++ = basis_32[(h[6] & 0x3f) >> 1];
222 :
223 0 : *p = '\0';
224 :
225 0 : return GSS_S_COMPLETE;
226 : }
227 :
228 : /*
229 : * gss_inquire_saslname_for_mech() wrapper that uses MIT SPI
230 : */
231 : static OM_uint32
232 0 : inquire_saslname_for_mech_compat(OM_uint32 *minor,
233 : const gss_OID desired_mech,
234 : gss_buffer_t sasl_mech_name,
235 : gss_buffer_t mech_name,
236 : gss_buffer_t mech_description)
237 : {
238 0 : struct gss_mech_compat_desc_struct *gmc;
239 0 : gssapi_mech_interface m;
240 0 : OM_uint32 major;
241 :
242 0 : m = __gss_get_mechanism(desired_mech);
243 0 : if (m == NULL)
244 0 : return GSS_S_BAD_MECH;
245 :
246 0 : gmc = m->gm_compat;
247 :
248 0 : if (gmc != NULL && gmc->gmc_inquire_saslname_for_mech != NULL) {
249 0 : major = gmc->gmc_inquire_saslname_for_mech(minor,
250 : desired_mech,
251 : sasl_mech_name,
252 : mech_name,
253 : mech_description);
254 : } else {
255 0 : major = GSS_S_UNAVAILABLE;
256 : }
257 :
258 0 : return major;
259 : }
260 :
261 : /**
262 : * Returns different protocol names and description of the mechanism.
263 : *
264 : * @param minor_status minor status code
265 : * @param desired_mech mech list query
266 : * @param sasl_mech_name SASL GS2 protocol name
267 : * @param mech_name gssapi protocol name
268 : * @param mech_description description of gssapi mech
269 : *
270 : * @return returns GSS_S_COMPLETE or a error code.
271 : *
272 : * @ingroup gssapi
273 : */
274 :
275 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
276 0 : gss_inquire_saslname_for_mech(OM_uint32 *minor_status,
277 : const gss_OID desired_mech,
278 : gss_buffer_t sasl_mech_name,
279 : gss_buffer_t mech_name,
280 : gss_buffer_t mech_description)
281 : {
282 0 : OM_uint32 major;
283 :
284 0 : _mg_buffer_zero(sasl_mech_name);
285 0 : _mg_buffer_zero(mech_name);
286 0 : _mg_buffer_zero(mech_description);
287 :
288 0 : if (minor_status)
289 0 : *minor_status = 0;
290 :
291 0 : if (desired_mech == NULL)
292 0 : return GSS_S_BAD_MECH;
293 :
294 0 : major = mo_value(desired_mech, GSS_C_MA_SASL_MECH_NAME, sasl_mech_name);
295 0 : if (major == GSS_S_COMPLETE) {
296 : /* Native SPI */
297 0 : major = mo_value(desired_mech, GSS_C_MA_MECH_NAME, mech_name);
298 0 : if (GSS_ERROR(major))
299 0 : return major;
300 :
301 0 : major = mo_value(desired_mech, GSS_C_MA_MECH_DESCRIPTION, mech_description);
302 0 : if (GSS_ERROR(major))
303 0 : return major;
304 : }
305 :
306 0 : if (GSS_ERROR(major)) {
307 : /* API-as-SPI compatibility */
308 0 : major = inquire_saslname_for_mech_compat(minor_status,
309 : desired_mech,
310 : sasl_mech_name,
311 : mech_name,
312 : mech_description);
313 : }
314 :
315 0 : if (GSS_ERROR(major)) {
316 : /* Algorithmically dervied SASL mechanism name */
317 0 : char buf[16];
318 0 : gss_buffer_desc tmp = { sizeof(buf) - 1, buf };
319 :
320 0 : major = make_sasl_name(minor_status, desired_mech, buf);
321 0 : if (GSS_ERROR(major))
322 0 : return major;
323 :
324 0 : major = _gss_copy_buffer(minor_status, &tmp, sasl_mech_name);
325 0 : if (GSS_ERROR(major))
326 0 : return major;
327 : }
328 :
329 0 : return major;
330 : }
331 :
332 : /**
333 : * Find a mech for a sasl name
334 : *
335 : * @param minor_status minor status code
336 : * @param sasl_mech_name
337 : * @param mech_type
338 : *
339 : * @return returns GSS_S_COMPLETE or an error code.
340 : */
341 :
342 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
343 0 : gss_inquire_mech_for_saslname(OM_uint32 *minor_status,
344 : const gss_buffer_t sasl_mech_name,
345 : gss_OID *mech_type)
346 : {
347 0 : struct _gss_mech_switch *m;
348 0 : gss_buffer_desc name;
349 0 : OM_uint32 major, junk;
350 0 : char buf[16];
351 :
352 0 : _gss_load_mech();
353 :
354 0 : *mech_type = NULL;
355 :
356 0 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
357 0 : struct gss_mech_compat_desc_struct *gmc;
358 :
359 : /* Native SPI */
360 0 : major = mo_value(m->gm_mech_oid, GSS_C_MA_SASL_MECH_NAME, &name);
361 0 : if (major == GSS_S_COMPLETE &&
362 0 : name.length == sasl_mech_name->length &&
363 0 : memcmp(name.value, sasl_mech_name->value, name.length) == 0) {
364 0 : gss_release_buffer(&junk, &name);
365 0 : *mech_type = m->gm_mech_oid;
366 0 : return GSS_S_COMPLETE;
367 : }
368 0 : gss_release_buffer(&junk, &name);
369 :
370 0 : if (GSS_ERROR(major)) {
371 : /* API-as-SPI compatibility */
372 0 : gmc = m->gm_mech.gm_compat;
373 0 : if (gmc && gmc->gmc_inquire_mech_for_saslname) {
374 0 : major = gmc->gmc_inquire_mech_for_saslname(minor_status,
375 : sasl_mech_name,
376 : mech_type);
377 0 : if (major == GSS_S_COMPLETE)
378 0 : return GSS_S_COMPLETE;
379 : }
380 : }
381 :
382 0 : if (GSS_ERROR(major)) {
383 : /* Algorithmically dervied SASL mechanism name */
384 0 : if (sasl_mech_name->length == 16 &&
385 0 : make_sasl_name(minor_status, m->gm_mech_oid, buf) == GSS_S_COMPLETE &&
386 0 : memcmp(buf, sasl_mech_name->value, 16) == 0) {
387 0 : *mech_type = m->gm_mech_oid;
388 0 : return GSS_S_COMPLETE;
389 : }
390 : }
391 : }
392 :
393 0 : return GSS_S_BAD_MECH;
394 : }
395 :
396 : /*
397 : * Test mechanism against indicated attributes using both Heimdal and
398 : * MIT SPIs.
399 : */
400 : static int
401 0 : test_mech_attrs(gssapi_mech_interface mi,
402 : gss_const_OID_set mech_attrs,
403 : gss_const_OID_set against_attrs,
404 : int except)
405 : {
406 0 : size_t n, m;
407 0 : int eq = 0;
408 :
409 0 : if (against_attrs == GSS_C_NO_OID_SET)
410 0 : return 1;
411 :
412 0 : for (n = 0; n < against_attrs->count; n++) {
413 0 : for (m = 0; m < mi->gm_mo_num; m++) {
414 0 : eq = gss_oid_equal(mi->gm_mo[m].option,
415 0 : &against_attrs->elements[n]);
416 0 : if (eq)
417 0 : break;
418 : }
419 0 : if (mech_attrs != GSS_C_NO_OID_SET) {
420 0 : for (m = 0; m < mech_attrs->count; m++) {
421 0 : eq = gss_oid_equal(&mech_attrs->elements[m],
422 0 : &against_attrs->elements[n]);
423 0 : if (eq)
424 0 : break;
425 : }
426 : }
427 0 : if (!eq ^ except)
428 0 : return 0;
429 : }
430 :
431 0 : return 1;
432 : }
433 :
434 : /**
435 : * Return set of mechanism that fullfill the criteria
436 : *
437 : * @param minor_status minor status code
438 : * @param desired_mech_attrs
439 : * @param except_mech_attrs
440 : * @param critical_mech_attrs
441 : * @param mechs returned mechs, free with gss_release_oid_set().
442 : *
443 : * @return returns GSS_S_COMPLETE or an error code.
444 : */
445 :
446 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
447 0 : gss_indicate_mechs_by_attrs(OM_uint32 * minor_status,
448 : gss_const_OID_set desired_mech_attrs,
449 : gss_const_OID_set except_mech_attrs,
450 : gss_const_OID_set critical_mech_attrs,
451 : gss_OID_set *mechs)
452 : {
453 0 : struct _gss_mech_switch *ms;
454 0 : gss_OID_set mech_attrs = GSS_C_NO_OID_SET;
455 0 : gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET;
456 0 : OM_uint32 major, tmp;
457 :
458 0 : major = gss_create_empty_oid_set(minor_status, mechs);
459 0 : if (GSS_ERROR(major))
460 0 : return major;
461 :
462 0 : _gss_load_mech();
463 :
464 0 : HEIM_TAILQ_FOREACH(ms, &_gss_mechs, gm_link) {
465 0 : gssapi_mech_interface mi = &ms->gm_mech;
466 0 : struct gss_mech_compat_desc_struct *gmc = mi->gm_compat;
467 :
468 0 : if (gmc && gmc->gmc_inquire_attrs_for_mech) {
469 0 : major = gmc->gmc_inquire_attrs_for_mech(minor_status,
470 0 : &mi->gm_mech_oid,
471 : &mech_attrs,
472 : &known_mech_attrs);
473 0 : if (GSS_ERROR(major))
474 0 : continue;
475 : }
476 :
477 : /*
478 : * Test mechanism supports all of desired_mech_attrs;
479 : * none of except_mech_attrs;
480 : * and knows of all critical_mech_attrs.
481 : */
482 0 : if (test_mech_attrs(mi, mech_attrs, desired_mech_attrs, 0) &&
483 0 : test_mech_attrs(mi, mech_attrs, except_mech_attrs, 1) &&
484 0 : test_mech_attrs(mi, known_mech_attrs, critical_mech_attrs, 0)) {
485 0 : major = gss_add_oid_set_member(minor_status, &mi->gm_mech_oid, mechs);
486 : }
487 :
488 0 : gss_release_oid_set(&tmp, &mech_attrs);
489 0 : gss_release_oid_set(&tmp, &known_mech_attrs);
490 :
491 0 : if (GSS_ERROR(major))
492 0 : break;
493 : }
494 :
495 0 : if (major)
496 0 : gss_release_oid_set(&tmp, mechs);
497 :
498 0 : return major;
499 : }
500 :
501 : /**
502 : * List support attributes for a mech and/or all mechanisms.
503 : *
504 : * @param minor_status minor status code
505 : * @param mech given together with mech_attr will return the list of
506 : * attributes for mechanism, can optionally be GSS_C_NO_OID.
507 : * @param mech_attr see mech parameter, can optionally be NULL,
508 : * release with gss_release_oid_set().
509 : * @param known_mech_attrs all attributes for mechanisms supported,
510 : * release with gss_release_oid_set().
511 : *
512 : * @ingroup gssapi
513 : */
514 :
515 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
516 0 : gss_inquire_attrs_for_mech(OM_uint32 * minor_status,
517 : gss_const_OID mech,
518 : gss_OID_set *mech_attr,
519 : gss_OID_set *known_mech_attrs)
520 : {
521 0 : OM_uint32 major, junk;
522 :
523 0 : if (known_mech_attrs)
524 0 : *known_mech_attrs = GSS_C_NO_OID_SET;
525 :
526 0 : if (mech_attr && mech) {
527 0 : gssapi_mech_interface m;
528 0 : struct gss_mech_compat_desc_struct *gmc;
529 :
530 0 : if ((m = __gss_get_mechanism(mech)) == NULL) {
531 0 : *minor_status = 0;
532 0 : return GSS_S_BAD_MECH;
533 : }
534 :
535 0 : gmc = m->gm_compat;
536 :
537 0 : if (gmc && gmc->gmc_inquire_attrs_for_mech) {
538 0 : major = gmc->gmc_inquire_attrs_for_mech(minor_status,
539 : mech,
540 : mech_attr,
541 : known_mech_attrs);
542 : } else {
543 0 : major = gss_create_empty_oid_set(minor_status, mech_attr);
544 0 : if (major == GSS_S_COMPLETE)
545 0 : add_all_mo(m, mech_attr, GSS_MO_MA);
546 : }
547 0 : if (GSS_ERROR(major))
548 0 : return major;
549 : }
550 :
551 0 : if (known_mech_attrs) {
552 0 : struct _gss_mech_switch *m;
553 :
554 0 : if (*known_mech_attrs == GSS_C_NO_OID_SET) {
555 0 : major = gss_create_empty_oid_set(minor_status, known_mech_attrs);
556 0 : if (GSS_ERROR(major)) {
557 0 : if (mech_attr)
558 0 : gss_release_oid_set(&junk, mech_attr);
559 0 : return major;
560 : }
561 : }
562 :
563 0 : _gss_load_mech();
564 :
565 0 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link)
566 0 : add_all_mo(&m->gm_mech, known_mech_attrs, GSS_MO_MA);
567 : }
568 :
569 :
570 0 : return GSS_S_COMPLETE;
571 : }
572 :
573 : /**
574 : * Return names and descriptions of mech attributes
575 : *
576 : * @param minor_status minor status code
577 : * @param mech_attr
578 : * @param name
579 : * @param short_desc
580 : * @param long_desc
581 : *
582 : * @return returns GSS_S_COMPLETE or an error code.
583 : */
584 :
585 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
586 0 : gss_display_mech_attr(OM_uint32 * minor_status,
587 : gss_const_OID mech_attr,
588 : gss_buffer_t name,
589 : gss_buffer_t short_desc,
590 : gss_buffer_t long_desc)
591 : {
592 0 : struct _gss_oid_name_table *ma = NULL;
593 0 : OM_uint32 major;
594 0 : size_t n;
595 :
596 0 : _mg_buffer_zero(name);
597 0 : _mg_buffer_zero(short_desc);
598 0 : _mg_buffer_zero(long_desc);
599 :
600 0 : if (minor_status)
601 0 : *minor_status = 0;
602 :
603 0 : for (n = 0; ma == NULL && _gss_ont_ma[n].oid; n++)
604 0 : if (gss_oid_equal(mech_attr, _gss_ont_ma[n].oid))
605 0 : ma = &_gss_ont_ma[n];
606 :
607 0 : if (ma == NULL)
608 0 : return GSS_S_BAD_MECH_ATTR;
609 :
610 0 : if (name) {
611 0 : gss_buffer_desc bd;
612 0 : bd.value = rk_UNCONST(ma->name);
613 0 : bd.length = strlen(ma->name);
614 0 : major = _gss_copy_buffer(minor_status, &bd, name);
615 0 : if (major != GSS_S_COMPLETE)
616 0 : return major;
617 : }
618 :
619 0 : if (short_desc) {
620 0 : gss_buffer_desc bd;
621 0 : bd.value = rk_UNCONST(ma->short_desc);
622 0 : bd.length = strlen(ma->short_desc);
623 0 : major = _gss_copy_buffer(minor_status, &bd, short_desc);
624 0 : if (major != GSS_S_COMPLETE)
625 0 : return major;
626 : }
627 :
628 0 : if (long_desc) {
629 0 : gss_buffer_desc bd;
630 0 : bd.value = rk_UNCONST(ma->long_desc);
631 0 : bd.length = strlen(ma->long_desc);
632 0 : major = _gss_copy_buffer(minor_status, &bd, long_desc);
633 0 : if (major != GSS_S_COMPLETE)
634 0 : return major;
635 : }
636 :
637 0 : return GSS_S_COMPLETE;
638 : }
|