1160814Ssimon/*- 2160814Ssimon * SPDX-License-Identifier: BSD-2-Clause 3160814Ssimon * 4160814Ssimon * Copyright (c) 2005 Doug Rabson 5160814Ssimon * All rights reserved. 6160814Ssimon * 7160814Ssimon * Redistribution and use in source and binary forms, with or without 8160814Ssimon * modification, are permitted provided that the following conditions 9280304Sjkim * are met: 10160814Ssimon * 1. Redistributions of source code must retain the above copyright 11160814Ssimon * notice, this list of conditions and the following disclaimer. 12160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 13160814Ssimon * notice, this list of conditions and the following disclaimer in the 14160814Ssimon * documentation and/or other materials provided with the distribution. 15160814Ssimon * 16160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17160814Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19160814Ssimon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21160814Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26160814Ssimon * SUCH DAMAGE. 27160814Ssimon */ 28160814Ssimon 29160814Ssimon#include <gssapi/gssapi.h> 30160814Ssimon#include <stdlib.h> 31160814Ssimon#include <string.h> 32160814Ssimon#include <errno.h> 33160814Ssimon 34160814Ssimon#include "mech_switch.h" 35160814Ssimon#include "utils.h" 36160814Ssimon#include "name.h" 37160814Ssimon 38160814Ssimonstatic OM_uint32 39160814Ssimon_gss_import_export_name(OM_uint32 *minor_status, 40160814Ssimon const gss_buffer_t input_name_buffer, 41160814Ssimon gss_name_t *output_name) 42280304Sjkim{ 43160814Ssimon OM_uint32 major_status; 44280304Sjkim unsigned char *p = input_name_buffer->value; 45280304Sjkim size_t len = input_name_buffer->length; 46160814Ssimon size_t t; 47280304Sjkim gss_OID_desc mech_oid; 48280304Sjkim struct _gss_mech_switch *m; 49280304Sjkim struct _gss_name *name; 50160814Ssimon gss_name_t new_canonical_name; 51280304Sjkim 52160814Ssimon *minor_status = 0; 53280304Sjkim *output_name = 0; 54160814Ssimon 55280304Sjkim /* 56194206Ssimon * Make sure that TOK_ID is {4, 1}. 57194206Ssimon */ 58194206Ssimon if (len < 2) 59280304Sjkim return (GSS_S_BAD_NAME); 60280304Sjkim if (p[0] != 4 || p[1] != 1) 61160814Ssimon return (GSS_S_BAD_NAME); 62238405Sjkim p += 2; 63280304Sjkim len -= 2; 64280304Sjkim 65280304Sjkim /* 66280304Sjkim * Get the mech length and the name length and sanity 67280304Sjkim * check the size of of the buffer. 68280304Sjkim */ 69280304Sjkim if (len < 2) 70280304Sjkim return (GSS_S_BAD_NAME); 71280304Sjkim t = (p[0] << 8) + p[1]; 72238405Sjkim p += 2; 73280304Sjkim len -= 2; 74280304Sjkim 75280304Sjkim /* 76280304Sjkim * Check the DER encoded OID to make sure it agrees with the 77280304Sjkim * length we just decoded. 78280304Sjkim */ 79160814Ssimon if (p[0] != 6) /* 6=OID */ 80238405Sjkim return (GSS_S_BAD_NAME); 81280304Sjkim p++; 82280304Sjkim len--; 83280304Sjkim t--; 84280304Sjkim if (p[0] & 0x80) { 85280304Sjkim int digits = p[0]; 86280304Sjkim p++; 87280304Sjkim len--; 88280304Sjkim t--; 89280304Sjkim mech_oid.length = 0; 90238405Sjkim while (digits--) { 91280304Sjkim mech_oid.length = (mech_oid.length << 8) | p[0]; 92280304Sjkim p++; 93280304Sjkim len--; 94280304Sjkim t--; 95280304Sjkim } 96280304Sjkim } else { 97160814Ssimon mech_oid.length = p[0]; 98280304Sjkim p++; 99160814Ssimon len--; 100280304Sjkim t--; 101280304Sjkim } 102160814Ssimon if (mech_oid.length != t) 103280304Sjkim return (GSS_S_BAD_NAME); 104280304Sjkim 105280304Sjkim mech_oid.elements = p; 106280304Sjkim 107160814Ssimon if (len < t + 4) 108280304Sjkim return (GSS_S_BAD_NAME); 109280304Sjkim p += t; 110280304Sjkim len -= t; 111280304Sjkim 112280304Sjkim t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 113160814Ssimon p += 4; 114280304Sjkim len -= 4; 115280304Sjkim 116280304Sjkim if (len != t) 117280304Sjkim return (GSS_S_BAD_NAME); 118280304Sjkim 119280304Sjkim m = _gss_find_mech_switch(&mech_oid); 120280304Sjkim if (!m) 121280304Sjkim return (GSS_S_BAD_MECH); 122280304Sjkim 123280304Sjkim /* 124280304Sjkim * Ask the mechanism to import the name. 125280304Sjkim */ 126280304Sjkim major_status = m->gm_import_name(minor_status, 127280304Sjkim input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); 128280304Sjkim if (major_status != GSS_S_COMPLETE) { 129280304Sjkim _gss_mg_error(m, major_status, *minor_status); 130280304Sjkim return (major_status); 131280304Sjkim } 132280304Sjkim 133280304Sjkim /* 134280304Sjkim * Now we make a new name and mark it as an MN. 135280304Sjkim */ 136160814Ssimon name = _gss_make_name(m, new_canonical_name); 137280304Sjkim if (!name) { 138160814Ssimon m->gm_release_name(minor_status, &new_canonical_name); 139280304Sjkim return (GSS_S_FAILURE); 140280304Sjkim } 141160814Ssimon 142280304Sjkim *output_name = (gss_name_t) name; 143280304Sjkim 144280304Sjkim *minor_status = 0; 145280304Sjkim return (GSS_S_COMPLETE); 146280304Sjkim} 147160814Ssimon 148280304SjkimOM_uint32 149280304Sjkimgss_import_name(OM_uint32 *minor_status, 150280304Sjkim const gss_buffer_t input_name_buffer, 151280304Sjkim const gss_OID input_name_type, 152280304Sjkim gss_name_t *output_name) 153280304Sjkim{ 154280304Sjkim gss_OID name_type = input_name_type; 155280304Sjkim OM_uint32 major_status; 156280304Sjkim struct _gss_name *name; 157280304Sjkim 158280304Sjkim *output_name = GSS_C_NO_NAME; 159280304Sjkim 160280304Sjkim if (input_name_buffer->length == 0) { 161160814Ssimon *minor_status = 0; 162280304Sjkim return (GSS_S_BAD_NAME); 163280304Sjkim } 164280304Sjkim 165280304Sjkim /* 166280304Sjkim * Use GSS_NT_USER_NAME as default name type. 167280304Sjkim */ 168280304Sjkim if (name_type == GSS_C_NO_OID) 169280304Sjkim name_type = GSS_C_NT_USER_NAME; 170280304Sjkim 171280304Sjkim /* 172280304Sjkim * If this is an exported name, we need to parse it to find 173280304Sjkim * the mechanism and then import it as an MN. See RFC 2743 174280304Sjkim * section 3.2 for a description of the format. 175280304Sjkim */ 176160814Ssimon if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { 177280304Sjkim return _gss_import_export_name(minor_status, 178280304Sjkim input_name_buffer, output_name); 179160814Ssimon } 180280304Sjkim 181280304Sjkim /* 182280304Sjkim * Only allow certain name types. This is pretty bogus - we 183280304Sjkim * should figure out the list of supported name types using 184160814Ssimon * gss_inquire_names_for_mech. 185280304Sjkim */ 186280304Sjkim if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME) 187280304Sjkim && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) 188280304Sjkim && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) 189280304Sjkim && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) 190160814Ssimon && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) 191280304Sjkim && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) 192280304Sjkim && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { 193160814Ssimon *minor_status = 0; 194280304Sjkim return (GSS_S_BAD_NAMETYPE); 195280304Sjkim } 196280304Sjkim 197280304Sjkim *minor_status = 0; 198280304Sjkim name = malloc(sizeof(struct _gss_name)); 199280304Sjkim if (!name) { 200160814Ssimon *minor_status = ENOMEM; 201280304Sjkim return (GSS_S_FAILURE); 202280304Sjkim } 203160814Ssimon memset(name, 0, sizeof(struct _gss_name)); 204280304Sjkim 205280304Sjkim major_status = _gss_copy_oid(minor_status, 206280304Sjkim name_type, &name->gn_type); 207280304Sjkim if (major_status) { 208280304Sjkim free(name); 209280304Sjkim return (GSS_S_FAILURE); 210280304Sjkim } 211280304Sjkim 212280304Sjkim major_status = _gss_copy_buffer(minor_status, 213160814Ssimon input_name_buffer, &name->gn_value); 214280304Sjkim if (major_status) { 215280304Sjkim gss_name_t rname = (gss_name_t)name; 216280304Sjkim gss_release_name(minor_status, &rname); 217280304Sjkim return (GSS_S_FAILURE); 218280304Sjkim } 219280304Sjkim 220280304Sjkim SLIST_INIT(&name->gn_mn); 221280304Sjkim 222280304Sjkim *output_name = (gss_name_t) name; 223280304Sjkim return (GSS_S_COMPLETE); 224280304Sjkim} 225280304Sjkim