1226031Sstas/* 2226031Sstas * Copyright (c) 2010 Kungliga Tekniska H��gskolan 3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4226031Sstas * All rights reserved. 5226031Sstas * 6226031Sstas * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 7226031Sstas * Portions Copyright (c) 2010 PADL Software Pty Ltd. All rights reserved. 8226031Sstas * 9226031Sstas * Redistribution and use in source and binary forms, with or without 10226031Sstas * modification, are permitted provided that the following conditions 11226031Sstas * are met: 12226031Sstas * 13226031Sstas * 1. Redistributions of source code must retain the above copyright 14226031Sstas * notice, this list of conditions and the following disclaimer. 15226031Sstas * 16226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 17226031Sstas * notice, this list of conditions and the following disclaimer in the 18226031Sstas * documentation and/or other materials provided with the distribution. 19226031Sstas * 20226031Sstas * 3. Neither the name of the Institute nor the names of its contributors 21226031Sstas * may be used to endorse or promote products derived from this software 22226031Sstas * without specific prior written permission. 23226031Sstas * 24226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 25226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 28226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34226031Sstas * SUCH DAMAGE. 35226031Sstas */ 36226031Sstas 37226031Sstas#include "mech_locl.h" 38226031Sstas 39226031Sstas#include <crypto-headers.h> 40226031Sstas 41226031Sstasstatic int 42226031Sstasget_option_def(int def, gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) 43226031Sstas{ 44226031Sstas return def; 45226031Sstas} 46226031Sstas 47226031Sstasint 48226031Sstas_gss_mo_get_option_1(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) 49226031Sstas{ 50226031Sstas return get_option_def(1, mech, mo, value); 51226031Sstas} 52226031Sstas 53226031Sstasint 54226031Sstas_gss_mo_get_option_0(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) 55226031Sstas{ 56226031Sstas return get_option_def(0, mech, mo, value); 57226031Sstas} 58226031Sstas 59226031Sstasint 60226031Sstas_gss_mo_get_ctx_as_string(gss_const_OID mech, gss_mo_desc *mo, gss_buffer_t value) 61226031Sstas{ 62226031Sstas if (value) { 63226031Sstas value->value = strdup((char *)mo->ctx); 64226031Sstas if (value->value == NULL) 65226031Sstas return GSS_S_FAILURE; 66226031Sstas value->length = strlen((char *)mo->ctx); 67226031Sstas } 68226031Sstas return GSS_S_COMPLETE; 69226031Sstas} 70226031Sstas 71226031SstasGSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL 72226031Sstasgss_mo_set(gss_const_OID mech, gss_const_OID option, 73226031Sstas int enable, gss_buffer_t value) 74226031Sstas{ 75226031Sstas gssapi_mech_interface m; 76226031Sstas size_t n; 77226031Sstas 78226031Sstas if ((m = __gss_get_mechanism(mech)) == NULL) 79226031Sstas return GSS_S_BAD_MECH; 80226031Sstas 81226031Sstas for (n = 0; n < m->gm_mo_num; n++) 82226031Sstas if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].set) 83226031Sstas return m->gm_mo[n].set(mech, &m->gm_mo[n], enable, value); 84226031Sstas 85226031Sstas return GSS_S_UNAVAILABLE; 86226031Sstas} 87226031Sstas 88226031SstasGSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL 89226031Sstasgss_mo_get(gss_const_OID mech, gss_const_OID option, gss_buffer_t value) 90226031Sstas{ 91226031Sstas gssapi_mech_interface m; 92226031Sstas size_t n; 93226031Sstas 94226031Sstas _mg_buffer_zero(value); 95226031Sstas 96226031Sstas if ((m = __gss_get_mechanism(mech)) == NULL) 97226031Sstas return GSS_S_BAD_MECH; 98226031Sstas 99226031Sstas for (n = 0; n < m->gm_mo_num; n++) 100226031Sstas if (gss_oid_equal(option, m->gm_mo[n].option) && m->gm_mo[n].get) 101226031Sstas return m->gm_mo[n].get(mech, &m->gm_mo[n], value); 102226031Sstas 103226031Sstas return GSS_S_UNAVAILABLE; 104226031Sstas} 105226031Sstas 106226031Sstasstatic void 107226031Sstasadd_all_mo(gssapi_mech_interface m, gss_OID_set *options, OM_uint32 mask) 108226031Sstas{ 109226031Sstas OM_uint32 minor; 110226031Sstas size_t n; 111226031Sstas 112226031Sstas for (n = 0; n < m->gm_mo_num; n++) 113226031Sstas if ((m->gm_mo[n].flags & mask) == mask) 114226031Sstas gss_add_oid_set_member(&minor, m->gm_mo[n].option, options); 115226031Sstas} 116226031Sstas 117226031SstasGSSAPI_LIB_FUNCTION void GSSAPI_LIB_CALL 118226031Sstasgss_mo_list(gss_const_OID mech, gss_OID_set *options) 119226031Sstas{ 120226031Sstas gssapi_mech_interface m; 121226031Sstas OM_uint32 major, minor; 122226031Sstas 123226031Sstas if (options == NULL) 124226031Sstas return; 125226031Sstas 126226031Sstas *options = GSS_C_NO_OID_SET; 127226031Sstas 128226031Sstas if ((m = __gss_get_mechanism(mech)) == NULL) 129226031Sstas return; 130226031Sstas 131226031Sstas major = gss_create_empty_oid_set(&minor, options); 132226031Sstas if (major != GSS_S_COMPLETE) 133226031Sstas return; 134226031Sstas 135226031Sstas add_all_mo(m, options, 0); 136226031Sstas} 137226031Sstas 138226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 139226031Sstasgss_mo_name(gss_const_OID mech, gss_const_OID option, gss_buffer_t name) 140226031Sstas{ 141226031Sstas gssapi_mech_interface m; 142226031Sstas size_t n; 143226031Sstas 144226031Sstas if (name == NULL) 145226031Sstas return GSS_S_BAD_NAME; 146226031Sstas 147226031Sstas if ((m = __gss_get_mechanism(mech)) == NULL) 148226031Sstas return GSS_S_BAD_MECH; 149226031Sstas 150226031Sstas for (n = 0; n < m->gm_mo_num; n++) { 151226031Sstas if (gss_oid_equal(option, m->gm_mo[n].option)) { 152226031Sstas /* 153226031Sstas * If there is no name, its because its a GSS_C_MA and 154226031Sstas * there is already a table for that. 155226031Sstas */ 156226031Sstas if (m->gm_mo[n].name) { 157226031Sstas name->value = strdup(m->gm_mo[n].name); 158226031Sstas if (name->value == NULL) 159226031Sstas return GSS_S_BAD_NAME; 160226031Sstas name->length = strlen(m->gm_mo[n].name); 161226031Sstas return GSS_S_COMPLETE; 162226031Sstas } else { 163226031Sstas OM_uint32 junk; 164226031Sstas return gss_display_mech_attr(&junk, option, 165226031Sstas NULL, name, NULL); 166226031Sstas } 167226031Sstas } 168226031Sstas } 169226031Sstas return GSS_S_BAD_NAME; 170226031Sstas} 171226031Sstas 172226031Sstas/* 173226031Sstas * Helper function to allow NULL name 174226031Sstas */ 175226031Sstas 176226031Sstasstatic OM_uint32 177226031Sstasmo_value(const gss_const_OID mech, gss_const_OID option, gss_buffer_t name) 178226031Sstas{ 179226031Sstas if (name == NULL) 180226031Sstas return GSS_S_COMPLETE; 181226031Sstas 182226031Sstas return gss_mo_get(mech, option, name); 183226031Sstas} 184226031Sstas 185226031Sstas/* code derived from draft-ietf-cat-sasl-gssapi-01 */ 186226031Sstasstatic char basis_32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 187226031Sstas 188226031Sstasstatic OM_uint32 189226031Sstasmake_sasl_name(OM_uint32 *minor, const gss_OID mech, char sasl_name[16]) 190226031Sstas{ 191226031Sstas EVP_MD_CTX *ctx; 192226031Sstas char *p = sasl_name; 193226031Sstas u_char hdr[2], hash[20], *h = hash; 194226031Sstas 195226031Sstas if (mech->length > 127) 196226031Sstas return GSS_S_BAD_MECH; 197226031Sstas 198226031Sstas hdr[0] = 0x06; 199226031Sstas hdr[1] = mech->length; 200226031Sstas 201226031Sstas ctx = EVP_MD_CTX_create(); 202226031Sstas EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 203226031Sstas EVP_DigestUpdate(ctx, hdr, 2); 204226031Sstas EVP_DigestUpdate(ctx, mech->elements, mech->length); 205226031Sstas EVP_DigestFinal_ex(ctx, hash, NULL); 206226031Sstas 207226031Sstas memcpy(p, "GS2-", 4); 208226031Sstas p += 4; 209226031Sstas 210226031Sstas *p++ = basis_32[(h[0] >> 3)]; 211226031Sstas *p++ = basis_32[((h[0] & 7) << 2) | (h[1] >> 6)]; 212226031Sstas *p++ = basis_32[(h[1] & 0x3f) >> 1]; 213226031Sstas *p++ = basis_32[((h[1] & 1) << 4) | (h[2] >> 4)]; 214226031Sstas *p++ = basis_32[((h[2] & 0xf) << 1) | (h[3] >> 7)]; 215226031Sstas *p++ = basis_32[(h[3] & 0x7f) >> 2]; 216226031Sstas *p++ = basis_32[((h[3] & 3) << 3) | (h[4] >> 5)]; 217226031Sstas *p++ = basis_32[(h[4] & 0x1f)]; 218226031Sstas *p++ = basis_32[(h[5] >> 3)]; 219226031Sstas *p++ = basis_32[((h[5] & 7) << 2) | (h[6] >> 6)]; 220226031Sstas *p++ = basis_32[(h[6] & 0x3f) >> 1]; 221226031Sstas 222226031Sstas *p = '\0'; 223226031Sstas 224226031Sstas return GSS_S_COMPLETE; 225226031Sstas} 226226031Sstas 227226031Sstas/* 228226031Sstas * gss_inquire_saslname_for_mech() wrapper that uses MIT SPI 229226031Sstas */ 230226031Sstasstatic OM_uint32 231226031Sstasinquire_saslname_for_mech_compat(OM_uint32 *minor, 232226031Sstas const gss_OID desired_mech, 233226031Sstas gss_buffer_t sasl_mech_name, 234226031Sstas gss_buffer_t mech_name, 235226031Sstas gss_buffer_t mech_description) 236226031Sstas{ 237226031Sstas struct gss_mech_compat_desc_struct *gmc; 238226031Sstas gssapi_mech_interface m; 239226031Sstas OM_uint32 major; 240226031Sstas 241226031Sstas m = __gss_get_mechanism(desired_mech); 242226031Sstas if (m == NULL) 243226031Sstas return GSS_S_BAD_MECH; 244226031Sstas 245226031Sstas gmc = m->gm_compat; 246226031Sstas 247226031Sstas if (gmc != NULL && gmc->gmc_inquire_saslname_for_mech != NULL) { 248226031Sstas major = gmc->gmc_inquire_saslname_for_mech(minor, 249226031Sstas desired_mech, 250226031Sstas sasl_mech_name, 251226031Sstas mech_name, 252226031Sstas mech_description); 253226031Sstas } else { 254226031Sstas major = GSS_S_UNAVAILABLE; 255226031Sstas } 256226031Sstas 257226031Sstas return major; 258226031Sstas} 259226031Sstas 260226031Sstas/** 261226031Sstas * Returns different protocol names and description of the mechanism. 262226031Sstas * 263226031Sstas * @param minor_status minor status code 264226031Sstas * @param desired_mech mech list query 265226031Sstas * @param sasl_mech_name SASL GS2 protocol name 266226031Sstas * @param mech_name gssapi protocol name 267226031Sstas * @param mech_description description of gssapi mech 268226031Sstas * 269226031Sstas * @return returns GSS_S_COMPLETE or a error code. 270226031Sstas * 271226031Sstas * @ingroup gssapi 272226031Sstas */ 273226031Sstas 274226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 275226031Sstasgss_inquire_saslname_for_mech(OM_uint32 *minor_status, 276226031Sstas const gss_OID desired_mech, 277226031Sstas gss_buffer_t sasl_mech_name, 278226031Sstas gss_buffer_t mech_name, 279226031Sstas gss_buffer_t mech_description) 280226031Sstas{ 281226031Sstas OM_uint32 major; 282226031Sstas 283226031Sstas _mg_buffer_zero(sasl_mech_name); 284226031Sstas _mg_buffer_zero(mech_name); 285226031Sstas _mg_buffer_zero(mech_description); 286226031Sstas 287226031Sstas if (minor_status) 288226031Sstas *minor_status = 0; 289226031Sstas 290226031Sstas if (desired_mech == NULL) 291226031Sstas return GSS_S_BAD_MECH; 292226031Sstas 293226031Sstas major = mo_value(desired_mech, GSS_C_MA_SASL_MECH_NAME, sasl_mech_name); 294226031Sstas if (major == GSS_S_COMPLETE) { 295226031Sstas /* Native SPI */ 296226031Sstas major = mo_value(desired_mech, GSS_C_MA_MECH_NAME, mech_name); 297226031Sstas if (GSS_ERROR(major)) 298226031Sstas return major; 299226031Sstas 300226031Sstas major = mo_value(desired_mech, GSS_C_MA_MECH_DESCRIPTION, mech_description); 301226031Sstas if (GSS_ERROR(major)) 302226031Sstas return major; 303226031Sstas } 304226031Sstas 305226031Sstas if (GSS_ERROR(major)) { 306226031Sstas /* API-as-SPI compatibility */ 307226031Sstas major = inquire_saslname_for_mech_compat(minor_status, 308226031Sstas desired_mech, 309226031Sstas sasl_mech_name, 310226031Sstas mech_name, 311226031Sstas mech_description); 312226031Sstas } 313226031Sstas 314226031Sstas if (GSS_ERROR(major)) { 315226031Sstas /* Algorithmically dervied SASL mechanism name */ 316226031Sstas char buf[16]; 317226031Sstas gss_buffer_desc tmp = { sizeof(buf) - 1, buf }; 318226031Sstas 319226031Sstas major = make_sasl_name(minor_status, desired_mech, buf); 320226031Sstas if (GSS_ERROR(major)) 321226031Sstas return major; 322226031Sstas 323226031Sstas major = _gss_copy_buffer(minor_status, &tmp, sasl_mech_name); 324226031Sstas if (GSS_ERROR(major)) 325226031Sstas return major; 326226031Sstas } 327226031Sstas 328226031Sstas return major; 329226031Sstas} 330226031Sstas 331226031Sstas/** 332226031Sstas * Find a mech for a sasl name 333226031Sstas * 334226031Sstas * @param minor_status minor status code 335226031Sstas * @param sasl_mech_name 336226031Sstas * @param mech_type 337226031Sstas * 338226031Sstas * @return returns GSS_S_COMPLETE or an error code. 339226031Sstas */ 340226031Sstas 341226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 342226031Sstasgss_inquire_mech_for_saslname(OM_uint32 *minor_status, 343226031Sstas const gss_buffer_t sasl_mech_name, 344226031Sstas gss_OID *mech_type) 345226031Sstas{ 346226031Sstas struct _gss_mech_switch *m; 347226031Sstas gss_buffer_desc name; 348226031Sstas OM_uint32 major, junk; 349226031Sstas char buf[16]; 350226031Sstas 351226031Sstas _gss_load_mech(); 352226031Sstas 353226031Sstas *mech_type = NULL; 354226031Sstas 355226031Sstas HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) { 356226031Sstas struct gss_mech_compat_desc_struct *gmc; 357226031Sstas 358226031Sstas /* Native SPI */ 359226031Sstas major = mo_value(&m->gm_mech_oid, GSS_C_MA_SASL_MECH_NAME, &name); 360226031Sstas if (major == GSS_S_COMPLETE && 361226031Sstas name.length == sasl_mech_name->length && 362226031Sstas memcmp(name.value, sasl_mech_name->value, name.length) == 0) { 363226031Sstas gss_release_buffer(&junk, &name); 364226031Sstas *mech_type = &m->gm_mech_oid; 365226031Sstas return GSS_S_COMPLETE; 366226031Sstas } 367226031Sstas gss_release_buffer(&junk, &name); 368226031Sstas 369226031Sstas if (GSS_ERROR(major)) { 370226031Sstas /* API-as-SPI compatibility */ 371226031Sstas gmc = m->gm_mech.gm_compat; 372226031Sstas if (gmc && gmc->gmc_inquire_mech_for_saslname) { 373226031Sstas major = gmc->gmc_inquire_mech_for_saslname(minor_status, 374226031Sstas sasl_mech_name, 375226031Sstas mech_type); 376226031Sstas if (major == GSS_S_COMPLETE) 377226031Sstas return GSS_S_COMPLETE; 378226031Sstas } 379226031Sstas } 380226031Sstas 381226031Sstas if (GSS_ERROR(major)) { 382226031Sstas /* Algorithmically dervied SASL mechanism name */ 383226031Sstas if (sasl_mech_name->length == 16 && 384226031Sstas make_sasl_name(minor_status, &m->gm_mech_oid, buf) == GSS_S_COMPLETE && 385226031Sstas memcmp(buf, sasl_mech_name->value, 16) == 0) { 386226031Sstas *mech_type = &m->gm_mech_oid; 387226031Sstas return GSS_S_COMPLETE; 388226031Sstas } 389226031Sstas } 390226031Sstas } 391226031Sstas 392226031Sstas return GSS_S_BAD_MECH; 393226031Sstas} 394226031Sstas 395226031Sstas/* 396226031Sstas * Test mechanism against indicated attributes using both Heimdal and 397226031Sstas * MIT SPIs. 398226031Sstas */ 399226031Sstasstatic int 400226031Sstastest_mech_attrs(gssapi_mech_interface mi, 401226031Sstas gss_const_OID_set mech_attrs, 402226031Sstas gss_const_OID_set against_attrs, 403226031Sstas int except) 404226031Sstas{ 405226031Sstas size_t n, m; 406226031Sstas int eq = 0; 407226031Sstas 408226031Sstas if (against_attrs == GSS_C_NO_OID_SET) 409226031Sstas return 1; 410226031Sstas 411226031Sstas for (n = 0; n < against_attrs->count; n++) { 412226031Sstas for (m = 0; m < mi->gm_mo_num; m++) { 413226031Sstas eq = gss_oid_equal(mi->gm_mo[m].option, 414226031Sstas &against_attrs->elements[n]); 415226031Sstas if (eq) 416226031Sstas break; 417226031Sstas } 418226031Sstas if (mech_attrs != GSS_C_NO_OID_SET) { 419226031Sstas for (m = 0; m < mech_attrs->count; m++) { 420226031Sstas eq = gss_oid_equal(&mech_attrs->elements[m], 421226031Sstas &against_attrs->elements[n]); 422226031Sstas if (eq) 423226031Sstas break; 424226031Sstas } 425226031Sstas } 426226031Sstas if (!eq ^ except) 427226031Sstas return 0; 428226031Sstas } 429226031Sstas 430226031Sstas return 1; 431226031Sstas} 432226031Sstas 433226031Sstas/** 434226031Sstas * Return set of mechanism that fullfill the criteria 435226031Sstas * 436226031Sstas * @param minor_status minor status code 437226031Sstas * @param desired_mech_attrs 438226031Sstas * @param except_mech_attrs 439226031Sstas * @param critical_mech_attrs 440226031Sstas * @param mechs returned mechs, free with gss_release_oid_set(). 441226031Sstas * 442226031Sstas * @return returns GSS_S_COMPLETE or an error code. 443226031Sstas */ 444226031Sstas 445226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 446226031Sstasgss_indicate_mechs_by_attrs(OM_uint32 * minor_status, 447226031Sstas gss_const_OID_set desired_mech_attrs, 448226031Sstas gss_const_OID_set except_mech_attrs, 449226031Sstas gss_const_OID_set critical_mech_attrs, 450226031Sstas gss_OID_set *mechs) 451226031Sstas{ 452226031Sstas struct _gss_mech_switch *ms; 453226031Sstas gss_OID_set mech_attrs = GSS_C_NO_OID_SET; 454226031Sstas gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET; 455226031Sstas OM_uint32 major; 456226031Sstas 457226031Sstas major = gss_create_empty_oid_set(minor_status, mechs); 458226031Sstas if (GSS_ERROR(major)) 459226031Sstas return major; 460226031Sstas 461226031Sstas _gss_load_mech(); 462226031Sstas 463226031Sstas HEIM_SLIST_FOREACH(ms, &_gss_mechs, gm_link) { 464226031Sstas gssapi_mech_interface mi = &ms->gm_mech; 465226031Sstas struct gss_mech_compat_desc_struct *gmc = mi->gm_compat; 466226031Sstas OM_uint32 tmp; 467226031Sstas 468226031Sstas if (gmc && gmc->gmc_inquire_attrs_for_mech) { 469226031Sstas major = gmc->gmc_inquire_attrs_for_mech(minor_status, 470226031Sstas &mi->gm_mech_oid, 471226031Sstas &mech_attrs, 472226031Sstas &known_mech_attrs); 473226031Sstas if (GSS_ERROR(major)) 474226031Sstas continue; 475226031Sstas } 476226031Sstas 477226031Sstas /* 478226031Sstas * Test mechanism supports all of desired_mech_attrs; 479226031Sstas * none of except_mech_attrs; 480226031Sstas * and knows of all critical_mech_attrs. 481226031Sstas */ 482226031Sstas if (test_mech_attrs(mi, mech_attrs, desired_mech_attrs, 0) && 483226031Sstas test_mech_attrs(mi, mech_attrs, except_mech_attrs, 1) && 484226031Sstas test_mech_attrs(mi, known_mech_attrs, critical_mech_attrs, 0)) { 485226031Sstas major = gss_add_oid_set_member(minor_status, &mi->gm_mech_oid, mechs); 486226031Sstas } 487226031Sstas 488226031Sstas gss_release_oid_set(&tmp, &mech_attrs); 489226031Sstas gss_release_oid_set(&tmp, &known_mech_attrs); 490226031Sstas 491226031Sstas if (GSS_ERROR(major)) 492226031Sstas break; 493226031Sstas } 494226031Sstas 495226031Sstas return major; 496226031Sstas} 497226031Sstas 498226031Sstas/** 499226031Sstas * List support attributes for a mech and/or all mechanisms. 500226031Sstas * 501226031Sstas * @param minor_status minor status code 502226031Sstas * @param mech given together with mech_attr will return the list of 503226031Sstas * attributes for mechanism, can optionally be GSS_C_NO_OID. 504226031Sstas * @param mech_attr see mech parameter, can optionally be NULL, 505226031Sstas * release with gss_release_oid_set(). 506226031Sstas * @param known_mech_attrs all attributes for mechanisms supported, 507226031Sstas * release with gss_release_oid_set(). 508226031Sstas * 509226031Sstas * @ingroup gssapi 510226031Sstas */ 511226031Sstas 512226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 513226031Sstasgss_inquire_attrs_for_mech(OM_uint32 * minor_status, 514226031Sstas gss_const_OID mech, 515226031Sstas gss_OID_set *mech_attr, 516226031Sstas gss_OID_set *known_mech_attrs) 517226031Sstas{ 518226031Sstas OM_uint32 major, junk; 519226031Sstas 520226031Sstas if (known_mech_attrs) 521226031Sstas *known_mech_attrs = GSS_C_NO_OID_SET; 522226031Sstas 523226031Sstas if (mech_attr && mech) { 524226031Sstas gssapi_mech_interface m; 525226031Sstas struct gss_mech_compat_desc_struct *gmc; 526226031Sstas 527226031Sstas if ((m = __gss_get_mechanism(mech)) == NULL) { 528226031Sstas *minor_status = 0; 529226031Sstas return GSS_S_BAD_MECH; 530226031Sstas } 531226031Sstas 532226031Sstas gmc = m->gm_compat; 533226031Sstas 534226031Sstas if (gmc && gmc->gmc_inquire_attrs_for_mech) { 535226031Sstas major = gmc->gmc_inquire_attrs_for_mech(minor_status, 536226031Sstas mech, 537226031Sstas mech_attr, 538226031Sstas known_mech_attrs); 539226031Sstas } else { 540226031Sstas major = gss_create_empty_oid_set(minor_status, mech_attr); 541226031Sstas if (major == GSS_S_COMPLETE) 542226031Sstas add_all_mo(m, mech_attr, GSS_MO_MA); 543226031Sstas } 544226031Sstas if (GSS_ERROR(major)) 545226031Sstas return major; 546226031Sstas } 547226031Sstas 548226031Sstas if (known_mech_attrs) { 549226031Sstas struct _gss_mech_switch *m; 550226031Sstas 551226031Sstas if (*known_mech_attrs == GSS_C_NO_OID_SET) { 552226031Sstas major = gss_create_empty_oid_set(minor_status, known_mech_attrs); 553226031Sstas if (GSS_ERROR(major)) { 554226031Sstas if (mech_attr) 555226031Sstas gss_release_oid_set(&junk, mech_attr); 556226031Sstas return major; 557226031Sstas } 558226031Sstas } 559226031Sstas 560226031Sstas _gss_load_mech(); 561226031Sstas 562226031Sstas HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) 563226031Sstas add_all_mo(&m->gm_mech, known_mech_attrs, GSS_MO_MA); 564226031Sstas } 565226031Sstas 566226031Sstas 567226031Sstas return GSS_S_COMPLETE; 568226031Sstas} 569226031Sstas 570226031Sstas/** 571226031Sstas * Return names and descriptions of mech attributes 572226031Sstas * 573226031Sstas * @param minor_status minor status code 574226031Sstas * @param mech_attr 575226031Sstas * @param name 576226031Sstas * @param short_desc 577226031Sstas * @param long_desc 578226031Sstas * 579226031Sstas * @return returns GSS_S_COMPLETE or an error code. 580226031Sstas */ 581226031Sstas 582226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 583226031Sstasgss_display_mech_attr(OM_uint32 * minor_status, 584226031Sstas gss_const_OID mech_attr, 585226031Sstas gss_buffer_t name, 586226031Sstas gss_buffer_t short_desc, 587226031Sstas gss_buffer_t long_desc) 588226031Sstas{ 589226031Sstas struct _gss_oid_name_table *ma = NULL; 590226031Sstas OM_uint32 major; 591226031Sstas size_t n; 592226031Sstas 593226031Sstas _mg_buffer_zero(name); 594226031Sstas _mg_buffer_zero(short_desc); 595226031Sstas _mg_buffer_zero(long_desc); 596226031Sstas 597226031Sstas if (minor_status) 598226031Sstas *minor_status = 0; 599226031Sstas 600226031Sstas for (n = 0; ma == NULL && _gss_ont_ma[n].oid; n++) 601226031Sstas if (gss_oid_equal(mech_attr, _gss_ont_ma[n].oid)) 602226031Sstas ma = &_gss_ont_ma[n]; 603226031Sstas 604226031Sstas if (ma == NULL) 605226031Sstas return GSS_S_BAD_MECH_ATTR; 606226031Sstas 607226031Sstas if (name) { 608226031Sstas gss_buffer_desc bd; 609226031Sstas bd.value = rk_UNCONST(ma->name); 610226031Sstas bd.length = strlen(ma->name); 611226031Sstas major = _gss_copy_buffer(minor_status, &bd, name); 612226031Sstas if (major != GSS_S_COMPLETE) 613226031Sstas return major; 614226031Sstas } 615226031Sstas 616226031Sstas if (short_desc) { 617226031Sstas gss_buffer_desc bd; 618226031Sstas bd.value = rk_UNCONST(ma->short_desc); 619226031Sstas bd.length = strlen(ma->short_desc); 620226031Sstas major = _gss_copy_buffer(minor_status, &bd, short_desc); 621226031Sstas if (major != GSS_S_COMPLETE) 622226031Sstas return major; 623226031Sstas } 624226031Sstas 625226031Sstas if (long_desc) { 626226031Sstas gss_buffer_desc bd; 627226031Sstas bd.value = rk_UNCONST(ma->long_desc); 628226031Sstas bd.length = strlen(ma->long_desc); 629226031Sstas major = _gss_copy_buffer(minor_status, &bd, long_desc); 630226031Sstas if (major != GSS_S_COMPLETE) 631226031Sstas return major; 632226031Sstas } 633226031Sstas 634226031Sstas return GSS_S_COMPLETE; 635226031Sstas} 636