1 /*- 2 * Copyright (c) 2005 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <gssapi/gssapi.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <errno.h> 33 34 #include "mech_switch.h" 35 #include "utils.h" 36 #include "name.h" 37 38 static OM_uint32 39 _gss_import_export_name(OM_uint32 *minor_status, 40 const gss_buffer_t input_name_buffer, 41 gss_name_t *output_name) 42 { 43 OM_uint32 major_status; 44 unsigned char *p = input_name_buffer->value; 45 size_t len = input_name_buffer->length; 46 size_t t; 47 gss_OID_desc mech_oid; 48 struct _gss_mech_switch *m; 49 struct _gss_name *name; 50 struct _gss_mechanism_name *mn; 51 gss_name_t new_canonical_name; 52 53 *minor_status = 0; 54 *output_name = 0; 55 56 /* 57 * Make sure that TOK_ID is {4, 1}. 58 */ 59 if (len < 2) 60 return (GSS_S_BAD_NAME); 61 if (p[0] != 4 || p[1] != 1) 62 return (GSS_S_BAD_NAME); 63 p += 2; 64 len -= 2; 65 66 /* 67 * Get the mech length and the name length and sanity 68 * check the size of of the buffer. 69 */ 70 if (len < 2) 71 return (GSS_S_BAD_NAME); 72 t = (p[0] << 8) + p[1]; 73 p += 2; 74 len -= 2; 75 76 /* 77 * Check the DER encoded OID to make sure it agrees with the 78 * length we just decoded. 79 */ 80 if (p[0] != 6) /* 6=OID */ 81 return (GSS_S_BAD_NAME); 82 p++; 83 len--; 84 t--; 85 if (p[0] & 0x80) { 86 int digits = p[0]; 87 p++; 88 len--; 89 t--; 90 mech_oid.length = 0; 91 while (digits--) { 92 mech_oid.length = (mech_oid.length << 8) | p[0]; 93 p++; 94 len--; 95 t--; 96 } 97 } else { 98 mech_oid.length = p[0]; 99 p++; 100 len--; 101 t--; 102 } 103 if (mech_oid.length != t) 104 return (GSS_S_BAD_NAME); 105 106 mech_oid.elements = p; 107 108 if (len < t + 4) 109 return (GSS_S_BAD_NAME); 110 p += t; 111 len -= t; 112 113 t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 114 p += 4; 115 len -= 4; 116 117 if (len != t) 118 return (GSS_S_BAD_NAME); 119 120 m = _gss_find_mech_switch(&mech_oid); 121 if (!m) 122 return (GSS_S_BAD_MECH); 123 124 /* 125 * Ask the mechanism to import the name. 126 */ 127 major_status = m->gm_import_name(minor_status, 128 input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); 129 130 /* 131 * Now we make a new name and mark it as an MN. 132 */ 133 name = _gss_make_name(m, new_canonical_name); 134 if (!name) { 135 m->gm_release_name(minor_status, &new_canonical_name); 136 return (GSS_S_FAILURE); 137 } 138 139 *output_name = (gss_name_t) name; 140 141 *minor_status = 0; 142 return (GSS_S_COMPLETE); 143 } 144 145 OM_uint32 146 gss_import_name(OM_uint32 *minor_status, 147 const gss_buffer_t input_name_buffer, 148 const gss_OID input_name_type, 149 gss_name_t *output_name) 150 { 151 gss_OID name_type = input_name_type; 152 OM_uint32 major_status; 153 struct _gss_name *name; 154 155 if (input_name_buffer->length == 0) { 156 *minor_status = 0; 157 *output_name = 0; 158 return (GSS_S_BAD_NAME); 159 } 160 161 /* 162 * Use GSS_NT_USER_NAME as default name type. 163 */ 164 if (name_type == GSS_C_NO_OID) 165 name_type = GSS_C_NT_USER_NAME; 166 167 /* 168 * If this is an exported name, we need to parse it to find 169 * the mechanism and then import it as an MN. See RFC 2743 170 * section 3.2 for a description of the format. 171 */ 172 if (_gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { 173 return _gss_import_export_name(minor_status, 174 input_name_buffer, output_name); 175 } 176 177 /* 178 * Only allow certain name types. This is pretty bogus - we 179 * should figure out the list of supported name types using 180 * gss_inquire_names_for_mech. 181 */ 182 if (!_gss_oid_equal(name_type, GSS_C_NT_USER_NAME) 183 && !_gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) 184 && !_gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) 185 && !_gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) 186 && !_gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) 187 && !_gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) 188 && !_gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { 189 *minor_status = 0; 190 *output_name = 0; 191 return (GSS_S_BAD_NAMETYPE); 192 } 193 194 *minor_status = 0; 195 name = malloc(sizeof(struct _gss_name)); 196 if (!name) { 197 *minor_status = ENOMEM; 198 return (GSS_S_FAILURE); 199 } 200 memset(name, 0, sizeof(struct _gss_name)); 201 202 major_status = _gss_copy_oid(minor_status, 203 name_type, &name->gn_type); 204 if (major_status) { 205 free(name); 206 return (GSS_S_FAILURE); 207 } 208 209 major_status = _gss_copy_buffer(minor_status, 210 input_name_buffer, &name->gn_value); 211 if (major_status) { 212 gss_release_name(minor_status, (gss_name_t*) &name); 213 return (GSS_S_FAILURE); 214 } 215 216 SLIST_INIT(&name->gn_mn); 217 218 *output_name = (gss_name_t) name; 219 return (GSS_S_COMPLETE); 220 } 221