1/*- 2 * Copyright (c) 2005 Doug Rabson 3 * All rights reserved. 4 * 5 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: src/lib/libgssapi/gss_names.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ 29 */ 30 31#include "mech_locl.h" 32 33 34OM_uint32 35_gss_find_mn(OM_uint32 *minor_status, struct _gss_name *name, gss_const_OID mech, 36 struct _gss_mechanism_name **output_mn) 37{ 38 OM_uint32 major_status; 39 gssapi_mech_interface m; 40 struct _gss_mechanism_name *mn; 41 42 *output_mn = NULL; 43 44 /* null names are ok, some mechs might not have names */ 45 if (name == NULL) 46 return GSS_S_COMPLETE; 47 48 HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { 49 if (gss_oid_equal(mech, mn->gmn_mech_oid)) 50 break; 51 } 52 53 if (!mn) { 54 /* 55 * If this name is canonical (i.e. there is only an 56 * MN but it is from a different mech), give up now. 57 */ 58 if (!name->gn_value.value) 59 return GSS_S_BAD_NAME; 60 61 m = __gss_get_mechanism(mech); 62 if (!m) 63 return (GSS_S_BAD_MECH); 64 65 mn = malloc(sizeof(struct _gss_mechanism_name)); 66 if (!mn) 67 return GSS_S_FAILURE; 68 69 major_status = m->gm_import_name(minor_status, 70 &name->gn_value, 71 (name->gn_type.elements 72 ? &name->gn_type : GSS_C_NO_OID), 73 &mn->gmn_name); 74 if (major_status != GSS_S_COMPLETE) { 75 _gss_mg_error(m, *minor_status); 76 free(mn); 77 return major_status; 78 } 79 80 mn->gmn_mech = m; 81 mn->gmn_mech_oid = &m->gm_mech_oid; 82 HEIM_SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); 83 } 84 *output_mn = mn; 85 return 0; 86} 87 88 89/* 90 * Make a name from an MN. 91 */ 92struct _gss_name * 93_gss_create_name(gss_name_t new_mn, struct gssapi_mech_interface_desc *m) 94{ 95 struct _gss_name *name; 96 struct _gss_mechanism_name *mn; 97 98 name = calloc(1, sizeof(struct _gss_name)); 99 if (!name) 100 return (0); 101 102 HEIM_SLIST_INIT(&name->gn_mn); 103 104 if (new_mn) { 105 mn = malloc(sizeof(struct _gss_mechanism_name)); 106 if (!mn) { 107 free(name); 108 return (0); 109 } 110 111 mn->gmn_mech = m; 112 mn->gmn_mech_oid = &m->gm_mech_oid; 113 mn->gmn_name = new_mn; 114 HEIM_SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); 115 } 116 117 return (name); 118} 119 120/* 121 * 122 */ 123 124void 125_gss_mg_release_name(struct _gss_name *name) 126{ 127 OM_uint32 junk; 128 129 _gss_free_oid(&junk, &name->gn_type); 130 131 while (HEIM_SLIST_FIRST(&name->gn_mn)) { 132 struct _gss_mechanism_name *mn; 133 mn = HEIM_SLIST_FIRST(&name->gn_mn); 134 HEIM_SLIST_REMOVE_HEAD(&name->gn_mn, gmn_link); 135 mn->gmn_mech->gm_release_name(&junk, &mn->gmn_name); 136 free(mn); 137 } 138 gss_release_buffer(&junk, &name->gn_value); 139 free(name); 140} 141 142void 143_gss_mg_check_name(gss_name_t name) 144{ 145 if (name == NULL) return; 146} 147 148/* 149 * 150 */ 151 152OM_uint32 153_gss_mech_import_name(OM_uint32 * minor_status, 154 gss_const_OID mech, 155 struct _gss_name_type *names, 156 const gss_buffer_t input_name_buffer, 157 gss_const_OID input_name_type, 158 gss_name_t * output_name) 159{ 160 struct _gss_name_type *name; 161 gss_buffer_t name_buffer = input_name_buffer; 162 gss_buffer_desc export_name; 163 164 *minor_status = 0; 165 166 if (output_name == NULL) 167 return GSS_S_CALL_INACCESSIBLE_WRITE; 168 169 *output_name = GSS_C_NO_NAME; 170 171 /* 172 * If its a exported name, strip of the mech glue. 173 */ 174 175 if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { 176 unsigned char *p; 177 uint32_t length; 178 179 if (name_buffer->length < 10 + mech->length) 180 return GSS_S_BAD_NAME; 181 182 /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ 183 184 p = name_buffer->value; 185 186 if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || 187 p[3] != mech->length + 2 || 188 p[4] != 0x06 || 189 p[5] != mech->length || 190 memcmp(&p[6], mech->elements, mech->length) != 0) 191 return GSS_S_BAD_NAME; 192 193 p += 6 + mech->length; 194 195 length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 196 p += 4; 197 198 if (length > name_buffer->length - 10 - mech->length) 199 return GSS_S_BAD_NAME; 200 201 /* 202 * Point this to the mech specific name part, don't modifity 203 * orignal input_name_buffer. 204 */ 205 206 export_name.length = length; 207 export_name.value = p; 208 209 name_buffer = &export_name; 210 } 211 212 for (name = names; name->gnt_parse != NULL; name++) { 213 if (gss_oid_equal(input_name_type, name->gnt_name_type) 214 || (name->gnt_name_type == GSS_C_NO_OID && input_name_type == GSS_C_NO_OID)) 215 return name->gnt_parse(minor_status, mech, name_buffer, 216 input_name_type, output_name); 217 } 218 219 return GSS_S_BAD_NAMETYPE; 220} 221 222OM_uint32 223_gss_mech_inquire_names_for_mech(OM_uint32 * minor_status, 224 struct _gss_name_type *names, 225 gss_OID_set * name_types) 226{ 227 struct _gss_name_type *name; 228 OM_uint32 ret; 229 230 ret = gss_create_empty_oid_set(minor_status, name_types); 231 if (ret != GSS_S_COMPLETE) 232 return ret; 233 234 for (name = names; name->gnt_parse != NULL; name++) { 235 if (name->gnt_name_type == GSS_C_NO_OID) 236 continue; 237 ret = gss_add_oid_set_member(minor_status, 238 name->gnt_name_type, 239 name_types); 240 if (ret != GSS_S_COMPLETE) 241 break; 242 } 243 244 if (ret != GSS_S_COMPLETE) 245 gss_release_oid_set(NULL, name_types); 246 247 return GSS_S_COMPLETE; 248} 249