1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/gssapi/mechglue/g_mechattr.c */ 3 /* 4 * Copyright (C) 2010 by the Massachusetts Institute of Technology. 5 * All rights reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include "mglueP.h" 28 29 static int 30 testMechAttr(gss_const_OID attr, 31 gss_const_OID_set against) 32 { 33 int present = 0; 34 OM_uint32 minor; 35 36 if (GSS_ERROR(generic_gss_test_oid_set_member(&minor, attr, 37 (gss_OID_set)against, 38 &present))) 39 return 0; 40 41 return present; 42 } 43 44 /* 45 * Return TRUE iff all the elements of desired and none of the elements 46 * of except exist in available. 47 */ 48 static int 49 testMechAttrsOffered(gss_const_OID_set desired, 50 gss_const_OID_set except, 51 gss_const_OID_set available) 52 { 53 size_t i; 54 55 if (desired != GSS_C_NO_OID_SET) { 56 for (i = 0; i < desired->count; i++) { 57 if (!testMechAttr(&desired->elements[i], available)) 58 return 0; 59 } 60 } 61 62 if (except != GSS_C_NO_OID_SET) { 63 for (i = 0; i < except->count; i++) { 64 if (testMechAttr(&except->elements[i], available)) 65 return 0; 66 } 67 } 68 69 return 1; 70 } 71 72 /* 73 * Return TRUE iff all the elements of critical exist in known. 74 */ 75 static int 76 testMechAttrsKnown(gss_const_OID_set critical, 77 gss_const_OID_set known) 78 { 79 size_t i; 80 81 if (critical != GSS_C_NO_OID_SET) { 82 for (i = 0; i < critical->count; i++) { 83 if (!testMechAttr(&critical->elements[i], known)) 84 return 0; 85 } 86 } 87 88 return 1; 89 } 90 91 OM_uint32 KRB5_CALLCONV 92 gss_indicate_mechs_by_attrs( 93 OM_uint32 *minor, 94 gss_const_OID_set desired_mech_attrs, 95 gss_const_OID_set except_mech_attrs, 96 gss_const_OID_set critical_mech_attrs, 97 gss_OID_set *mechs) 98 { 99 OM_uint32 status, tmpMinor; 100 gss_OID_set allMechs = GSS_C_NO_OID_SET; 101 size_t i; 102 103 if (minor != NULL) 104 *minor = 0; 105 106 if (mechs != NULL) 107 *mechs = GSS_C_NO_OID_SET; 108 109 if (minor == NULL || mechs == NULL) 110 return GSS_S_CALL_INACCESSIBLE_WRITE; 111 112 status = gss_indicate_mechs(minor, &allMechs); 113 if (GSS_ERROR(status)) 114 goto cleanup; 115 116 status = generic_gss_create_empty_oid_set(minor, mechs); 117 if (GSS_ERROR(status)) 118 goto cleanup; 119 120 for (i = 0; i < allMechs->count; i++) { 121 gss_OID_set supportedAttrs = GSS_C_NO_OID_SET; 122 gss_OID_set knownAttrs = GSS_C_NO_OID_SET; 123 124 status = gss_inquire_attrs_for_mech(minor, &allMechs->elements[i], 125 &supportedAttrs, &knownAttrs); 126 if (GSS_ERROR(status)) 127 continue; 128 129 if (testMechAttrsOffered(desired_mech_attrs, 130 except_mech_attrs, supportedAttrs) && 131 testMechAttrsKnown(critical_mech_attrs, knownAttrs)) { 132 status = gss_add_oid_set_member(minor, &allMechs->elements[i], 133 mechs); 134 if (GSS_ERROR(status)) { 135 gss_release_oid_set(&tmpMinor, &supportedAttrs); 136 gss_release_oid_set(&tmpMinor, &knownAttrs); 137 goto cleanup; 138 } 139 } 140 141 gss_release_oid_set(&tmpMinor, &supportedAttrs); 142 gss_release_oid_set(&tmpMinor, &knownAttrs); 143 } 144 145 *minor = 0; 146 status = GSS_S_COMPLETE; 147 148 cleanup: 149 gss_release_oid_set(&tmpMinor, &allMechs); 150 151 return status; 152 } 153 154 OM_uint32 KRB5_CALLCONV 155 gss_inquire_attrs_for_mech( 156 OM_uint32 *minor, 157 gss_const_OID mech_oid, 158 gss_OID_set *mech_attrs, 159 gss_OID_set *known_mech_attrs) 160 { 161 OM_uint32 status, tmpMinor; 162 gss_OID selected_mech, public_mech; 163 gss_mechanism mech; 164 165 if (minor != NULL) 166 *minor = 0; 167 168 if (mech_attrs != NULL) 169 *mech_attrs = GSS_C_NO_OID_SET; 170 171 if (known_mech_attrs != NULL) 172 *known_mech_attrs = GSS_C_NO_OID_SET; 173 174 if (minor == NULL) 175 return GSS_S_CALL_INACCESSIBLE_WRITE; 176 177 status = gssint_select_mech_type(minor, mech_oid, &selected_mech); 178 if (status != GSS_S_COMPLETE) 179 return status; 180 181 mech = gssint_get_mechanism(selected_mech); 182 if (mech == NULL) 183 return GSS_S_BAD_MECH; 184 185 /* If the mech does not implement RFC 5587, return success with an empty 186 * mech_attrs and known_mech_attrs. */ 187 if (mech->gss_inquire_attrs_for_mech == NULL) 188 return GSS_S_COMPLETE; 189 190 public_mech = gssint_get_public_oid(selected_mech); 191 status = mech->gss_inquire_attrs_for_mech(minor, public_mech, mech_attrs, 192 known_mech_attrs); 193 if (GSS_ERROR(status)) { 194 map_error(minor, mech); 195 return status; 196 } 197 198 if (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) { 199 status = generic_gss_copy_oid_set(minor, 200 gss_ma_known_attrs, 201 known_mech_attrs); 202 if (GSS_ERROR(status)) { 203 gss_release_oid_set(&tmpMinor, mech_attrs); 204 if (mech_attrs != NULL) 205 *mech_attrs = GSS_C_NO_OID_SET; 206 } 207 } 208 209 return GSS_S_COMPLETE; 210 } 211 212 OM_uint32 KRB5_CALLCONV 213 gss_display_mech_attr( 214 OM_uint32 *minor, 215 gss_const_OID mech_attr, 216 gss_buffer_t name, 217 gss_buffer_t short_desc, 218 gss_buffer_t long_desc) 219 { 220 return generic_gss_display_mech_attr(minor, mech_attr, 221 name, short_desc, long_desc); 222 } 223