1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005 Doug Rabson 5 * 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$ 29 */ 30 31 #include <gssapi/gssapi.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 36 #include "mech_switch.h" 37 #include "utils.h" 38 #include "name.h" 39 40 static OM_uint32 41 _gss_import_export_name(OM_uint32 *minor_status, 42 const gss_buffer_t input_name_buffer, 43 gss_name_t *output_name) 44 { 45 OM_uint32 major_status; 46 unsigned char *p = input_name_buffer->value; 47 size_t len = input_name_buffer->length; 48 size_t t; 49 gss_OID_desc mech_oid; 50 struct _gss_mech_switch *m; 51 struct _gss_name *name; 52 gss_name_t new_canonical_name; 53 54 *minor_status = 0; 55 *output_name = 0; 56 57 /* 58 * Make sure that TOK_ID is {4, 1}. 59 */ 60 if (len < 2) 61 return (GSS_S_BAD_NAME); 62 if (p[0] != 4 || p[1] != 1) 63 return (GSS_S_BAD_NAME); 64 p += 2; 65 len -= 2; 66 67 /* 68 * Get the mech length and the name length and sanity 69 * check the size of of the buffer. 70 */ 71 if (len < 2) 72 return (GSS_S_BAD_NAME); 73 t = (p[0] << 8) + p[1]; 74 p += 2; 75 len -= 2; 76 77 /* 78 * Check the DER encoded OID to make sure it agrees with the 79 * length we just decoded. 80 */ 81 if (p[0] != 6) /* 6=OID */ 82 return (GSS_S_BAD_NAME); 83 p++; 84 len--; 85 t--; 86 if (p[0] & 0x80) { 87 int digits = p[0]; 88 p++; 89 len--; 90 t--; 91 mech_oid.length = 0; 92 while (digits--) { 93 mech_oid.length = (mech_oid.length << 8) | p[0]; 94 p++; 95 len--; 96 t--; 97 } 98 } else { 99 mech_oid.length = p[0]; 100 p++; 101 len--; 102 t--; 103 } 104 if (mech_oid.length != t) 105 return (GSS_S_BAD_NAME); 106 107 mech_oid.elements = p; 108 109 if (len < t + 4) 110 return (GSS_S_BAD_NAME); 111 p += t; 112 len -= t; 113 114 t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 115 p += 4; 116 len -= 4; 117 118 if (len != t) 119 return (GSS_S_BAD_NAME); 120 121 m = _gss_find_mech_switch(&mech_oid); 122 if (!m) 123 return (GSS_S_BAD_MECH); 124 125 /* 126 * Ask the mechanism to import the name. 127 */ 128 major_status = m->gm_import_name(minor_status, 129 input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); 130 if (major_status != GSS_S_COMPLETE) { 131 _gss_mg_error(m, major_status, *minor_status); 132 return (major_status); 133 } 134 135 /* 136 * Now we make a new name and mark it as an MN. 137 */ 138 name = _gss_make_name(m, new_canonical_name); 139 if (!name) { 140 m->gm_release_name(minor_status, &new_canonical_name); 141 return (GSS_S_FAILURE); 142 } 143 144 *output_name = (gss_name_t) name; 145 146 *minor_status = 0; 147 return (GSS_S_COMPLETE); 148 } 149 150 OM_uint32 151 gss_import_name(OM_uint32 *minor_status, 152 const gss_buffer_t input_name_buffer, 153 const gss_OID input_name_type, 154 gss_name_t *output_name) 155 { 156 gss_OID name_type = input_name_type; 157 OM_uint32 major_status; 158 struct _gss_name *name; 159 160 *output_name = GSS_C_NO_NAME; 161 162 if (input_name_buffer->length == 0) { 163 *minor_status = 0; 164 return (GSS_S_BAD_NAME); 165 } 166 167 /* 168 * Use GSS_NT_USER_NAME as default name type. 169 */ 170 if (name_type == GSS_C_NO_OID) 171 name_type = GSS_C_NT_USER_NAME; 172 173 /* 174 * If this is an exported name, we need to parse it to find 175 * the mechanism and then import it as an MN. See RFC 2743 176 * section 3.2 for a description of the format. 177 */ 178 if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { 179 return _gss_import_export_name(minor_status, 180 input_name_buffer, output_name); 181 } 182 183 /* 184 * Only allow certain name types. This is pretty bogus - we 185 * should figure out the list of supported name types using 186 * gss_inquire_names_for_mech. 187 */ 188 if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME) 189 && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) 190 && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) 191 && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) 192 && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) 193 && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) 194 && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { 195 *minor_status = 0; 196 return (GSS_S_BAD_NAMETYPE); 197 } 198 199 *minor_status = 0; 200 name = malloc(sizeof(struct _gss_name)); 201 if (!name) { 202 *minor_status = ENOMEM; 203 return (GSS_S_FAILURE); 204 } 205 memset(name, 0, sizeof(struct _gss_name)); 206 207 major_status = _gss_copy_oid(minor_status, 208 name_type, &name->gn_type); 209 if (major_status) { 210 free(name); 211 return (GSS_S_FAILURE); 212 } 213 214 major_status = _gss_copy_buffer(minor_status, 215 input_name_buffer, &name->gn_value); 216 if (major_status) { 217 gss_name_t rname = (gss_name_t)name; 218 gss_release_name(minor_status, &rname); 219 return (GSS_S_FAILURE); 220 } 221 222 SLIST_INIT(&name->gn_mn); 223 224 *output_name = (gss_name_t) name; 225 return (GSS_S_COMPLETE); 226 } 227