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