gss_import_name.c revision 178828
1169695Skan/*- 2169695Skan * Copyright (c) 2005 Doug Rabson 3169695Skan * All rights reserved. 4169695Skan * 5169695Skan * Redistribution and use in source and binary forms, with or without 6169695Skan * modification, are permitted provided that the following conditions 7169695Skan * are met: 8169695Skan * 1. Redistributions of source code must retain the above copyright 9169695Skan * notice, this list of conditions and the following disclaimer. 10169695Skan * 2. Redistributions in binary form must reproduce the above copyright 11169695Skan * notice, this list of conditions and the following disclaimer in the 12169695Skan * documentation and/or other materials provided with the distribution. 13169695Skan * 14169695Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17169695Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18169695Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169695Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169695Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169695Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169695Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23169695Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24169695Skan * SUCH DAMAGE. 25169695Skan * 26169695Skan * $FreeBSD: head/lib/libgssapi/gss_import_name.c 178828 2008-05-07 13:53:12Z dfr $ 27169695Skan */ 28169695Skan 29169695Skan#include <gssapi/gssapi.h> 30169695Skan#include <stdlib.h> 31169695Skan#include <string.h> 32169695Skan#include <errno.h> 33169695Skan 34169695Skan#include "mech_switch.h" 35169695Skan#include "utils.h" 36169695Skan#include "name.h" 37169695Skan 38169695Skanstatic OM_uint32 39169695Skan_gss_import_export_name(OM_uint32 *minor_status, 40169695Skan const gss_buffer_t input_name_buffer, 41169695Skan gss_name_t *output_name) 42169695Skan{ 43169695Skan OM_uint32 major_status; 44169695Skan unsigned char *p = input_name_buffer->value; 45169695Skan size_t len = input_name_buffer->length; 46169695Skan size_t t; 47169695Skan gss_OID_desc mech_oid; 48169695Skan struct _gss_mech_switch *m; 49169695Skan struct _gss_name *name; 50169695Skan gss_name_t new_canonical_name; 51169695Skan 52169695Skan *minor_status = 0; 53169695Skan *output_name = 0; 54169695Skan 55169695Skan /* 56169695Skan * Make sure that TOK_ID is {4, 1}. 57169695Skan */ 58169695Skan if (len < 2) 59169695Skan return (GSS_S_BAD_NAME); 60169695Skan if (p[0] != 4 || p[1] != 1) 61282152Spfg return (GSS_S_BAD_NAME); 62169695Skan p += 2; 63169695Skan len -= 2; 64169695Skan 65282152Spfg /* 66169695Skan * Get the mech length and the name length and sanity 67169695Skan * check the size of of the buffer. 68169695Skan */ 69169695Skan if (len < 2) 70169695Skan return (GSS_S_BAD_NAME); 71169695Skan t = (p[0] << 8) + p[1]; 72169695Skan p += 2; 73169695Skan len -= 2; 74169695Skan 75169695Skan /* 76169695Skan * Check the DER encoded OID to make sure it agrees with the 77169695Skan * length we just decoded. 78169695Skan */ 79169695Skan if (p[0] != 6) /* 6=OID */ 80169695Skan return (GSS_S_BAD_NAME); 81169695Skan p++; 82169695Skan len--; 83169695Skan t--; 84169695Skan if (p[0] & 0x80) { 85169695Skan int digits = p[0]; 86169695Skan p++; 87169695Skan len--; 88169695Skan t--; 89169695Skan mech_oid.length = 0; 90169695Skan while (digits--) { 91169695Skan mech_oid.length = (mech_oid.length << 8) | p[0]; 92169695Skan p++; 93169695Skan len--; 94169695Skan t--; 95169695Skan } 96169695Skan } else { 97169695Skan mech_oid.length = p[0]; 98169695Skan p++; 99169695Skan len--; 100169695Skan t--; 101169695Skan } 102169695Skan if (mech_oid.length != t) 103169695Skan return (GSS_S_BAD_NAME); 104169695Skan 105169695Skan mech_oid.elements = p; 106169695Skan 107169695Skan if (len < t + 4) 108169695Skan return (GSS_S_BAD_NAME); 109169695Skan p += t; 110169695Skan len -= t; 111169695Skan 112169695Skan t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 113169695Skan p += 4; 114169695Skan len -= 4; 115169695Skan 116169695Skan if (len != t) 117169695Skan return (GSS_S_BAD_NAME); 118169695Skan 119169695Skan m = _gss_find_mech_switch(&mech_oid); 120169695Skan if (!m) 121169695Skan return (GSS_S_BAD_MECH); 122169695Skan 123169695Skan /* 124169695Skan * Ask the mechanism to import the name. 125169695Skan */ 126169695Skan major_status = m->gm_import_name(minor_status, 127169695Skan input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); 128169695Skan if (major_status != GSS_S_COMPLETE) { 129169695Skan _gss_mg_error(m, major_status, *minor_status); 130169695Skan return (major_status); 131169695Skan } 132282152Spfg 133169695Skan /* 134169695Skan * Now we make a new name and mark it as an MN. 135169695Skan */ 136169695Skan name = _gss_make_name(m, new_canonical_name); 137169695Skan if (!name) { 138169695Skan m->gm_release_name(minor_status, &new_canonical_name); 139169695Skan return (GSS_S_FAILURE); 140169695Skan } 141169695Skan 142169695Skan *output_name = (gss_name_t) name; 143169695Skan 144169695Skan *minor_status = 0; 145169695Skan return (GSS_S_COMPLETE); 146169695Skan} 147169695Skan 148169695SkanOM_uint32 149169695Skangss_import_name(OM_uint32 *minor_status, 150169695Skan const gss_buffer_t input_name_buffer, 151169695Skan const gss_OID input_name_type, 152169695Skan gss_name_t *output_name) 153169695Skan{ 154169695Skan gss_OID name_type = input_name_type; 155169695Skan OM_uint32 major_status; 156169695Skan struct _gss_name *name; 157282201Spfg 158169695Skan *output_name = GSS_C_NO_NAME; 159169695Skan 160169695Skan if (input_name_buffer->length == 0) { 161169695Skan *minor_status = 0; 162169695Skan return (GSS_S_BAD_NAME); 163169695Skan } 164169695Skan 165169695Skan /* 166169695Skan * Use GSS_NT_USER_NAME as default name type. 167169695Skan */ 168169695Skan if (name_type == GSS_C_NO_OID) 169169695Skan name_type = GSS_C_NT_USER_NAME; 170169695Skan 171169695Skan /* 172169695Skan * If this is an exported name, we need to parse it to find 173169695Skan * the mechanism and then import it as an MN. See RFC 2743 174169695Skan * section 3.2 for a description of the format. 175169695Skan */ 176169695Skan if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { 177169695Skan return _gss_import_export_name(minor_status, 178169695Skan input_name_buffer, output_name); 179169695Skan } 180169695Skan 181169695Skan /* 182169695Skan * Only allow certain name types. This is pretty bogus - we 183169695Skan * should figure out the list of supported name types using 184169695Skan * gss_inquire_names_for_mech. 185169695Skan */ 186169695Skan if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME) 187169695Skan && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) 188169695Skan && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) 189169695Skan && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) 190169695Skan && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) 191169695Skan && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) 192282152Spfg && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { 193282152Spfg *minor_status = 0; 194282115Spfg return (GSS_S_BAD_NAMETYPE); 195282115Spfg } 196282115Spfg 197282115Spfg *minor_status = 0; 198282115Spfg name = malloc(sizeof(struct _gss_name)); 199282115Spfg if (!name) { 200282115Spfg *minor_status = ENOMEM; 201282115Spfg return (GSS_S_FAILURE); 202282115Spfg } 203282115Spfg memset(name, 0, sizeof(struct _gss_name)); 204282115Spfg 205282115Spfg major_status = _gss_copy_oid(minor_status, 206282115Spfg name_type, &name->gn_type); 207282115Spfg if (major_status) { 208282115Spfg free(name); 209282115Spfg return (GSS_S_FAILURE); 210282115Spfg } 211282115Spfg 212282115Spfg major_status = _gss_copy_buffer(minor_status, 213169695Skan input_name_buffer, &name->gn_value); 214169695Skan if (major_status) { 215169695Skan gss_name_t rname = (gss_name_t)name; 216169695Skan gss_release_name(minor_status, &rname); 217169695Skan return (GSS_S_FAILURE); 218169695Skan } 219169695Skan 220169695Skan SLIST_INIT(&name->gn_mn); 221169695Skan 222169695Skan *output_name = (gss_name_t) name; 223169695Skan return (GSS_S_COMPLETE); 224169695Skan} 225169695Skan