1178825Sdfr/* 2233294Sstas * Copyright (c) 1997 - 2003 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34233294Sstas#include "gsskrb5_locl.h" 35178825Sdfr 36178825Sdfrstatic OM_uint32 37178825Sdfrparse_krb5_name (OM_uint32 *minor_status, 38178825Sdfr krb5_context context, 39178825Sdfr const char *name, 40178825Sdfr gss_name_t *output_name) 41178825Sdfr{ 42178825Sdfr krb5_principal princ; 43178825Sdfr krb5_error_code kerr; 44178825Sdfr 45178825Sdfr kerr = krb5_parse_name (context, name, &princ); 46178825Sdfr 47178825Sdfr if (kerr == 0) { 48178825Sdfr *output_name = (gss_name_t)princ; 49178825Sdfr return GSS_S_COMPLETE; 50178825Sdfr } 51178825Sdfr *minor_status = kerr; 52178825Sdfr 53178825Sdfr if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) 54178825Sdfr return GSS_S_BAD_NAME; 55178825Sdfr 56178825Sdfr return GSS_S_FAILURE; 57178825Sdfr} 58178825Sdfr 59178825Sdfrstatic OM_uint32 60178825Sdfrimport_krb5_name (OM_uint32 *minor_status, 61178825Sdfr krb5_context context, 62178825Sdfr const gss_buffer_t input_name_buffer, 63178825Sdfr gss_name_t *output_name) 64178825Sdfr{ 65178825Sdfr OM_uint32 ret; 66178825Sdfr char *tmp; 67178825Sdfr 68178825Sdfr tmp = malloc (input_name_buffer->length + 1); 69178825Sdfr if (tmp == NULL) { 70178825Sdfr *minor_status = ENOMEM; 71178825Sdfr return GSS_S_FAILURE; 72178825Sdfr } 73178825Sdfr memcpy (tmp, 74178825Sdfr input_name_buffer->value, 75178825Sdfr input_name_buffer->length); 76178825Sdfr tmp[input_name_buffer->length] = '\0'; 77178825Sdfr 78178825Sdfr ret = parse_krb5_name(minor_status, context, tmp, output_name); 79178825Sdfr free(tmp); 80178825Sdfr 81178825Sdfr return ret; 82178825Sdfr} 83178825Sdfr 84233294SstasOM_uint32 85233294Sstas_gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context, 86233294Sstas int use_dns, krb5_const_principal sourcename, gss_name_t targetname, 87233294Sstas krb5_principal *out) 88233294Sstas{ 89233294Sstas krb5_principal p = (krb5_principal)targetname; 90233294Sstas krb5_error_code ret; 91233294Sstas char *hostname = NULL, *service; 92233294Sstas 93233294Sstas *minor_status = 0; 94233294Sstas 95233294Sstas /* If its not a hostname */ 96233294Sstas if (krb5_principal_get_type(context, p) != MAGIC_HOSTBASED_NAME_TYPE) { 97233294Sstas ret = krb5_copy_principal(context, p, out); 98233294Sstas } else if (!use_dns) { 99233294Sstas ret = krb5_copy_principal(context, p, out); 100233294Sstas if (ret) 101233294Sstas goto out; 102233294Sstas krb5_principal_set_type(context, *out, KRB5_NT_SRV_HST); 103233294Sstas if (sourcename) 104233294Sstas ret = krb5_principal_set_realm(context, *out, sourcename->realm); 105233294Sstas } else { 106233294Sstas if (p->name.name_string.len == 0) 107233294Sstas return GSS_S_BAD_NAME; 108233294Sstas else if (p->name.name_string.len > 1) 109233294Sstas hostname = p->name.name_string.val[1]; 110233294Sstas 111233294Sstas service = p->name.name_string.val[0]; 112233294Sstas 113233294Sstas ret = krb5_sname_to_principal(context, 114233294Sstas hostname, 115233294Sstas service, 116233294Sstas KRB5_NT_SRV_HST, 117233294Sstas out); 118233294Sstas } 119233294Sstas 120233294Sstas out: 121233294Sstas if (ret) { 122233294Sstas *minor_status = ret; 123233294Sstas return GSS_S_FAILURE; 124233294Sstas } 125233294Sstas 126233294Sstas return 0; 127233294Sstas} 128233294Sstas 129233294Sstas 130178825Sdfrstatic OM_uint32 131178825Sdfrimport_hostbased_name (OM_uint32 *minor_status, 132178825Sdfr krb5_context context, 133178825Sdfr const gss_buffer_t input_name_buffer, 134178825Sdfr gss_name_t *output_name) 135178825Sdfr{ 136233294Sstas krb5_principal princ = NULL; 137178825Sdfr krb5_error_code kerr; 138233294Sstas char *tmp, *p, *host = NULL; 139178825Sdfr 140178825Sdfr tmp = malloc (input_name_buffer->length + 1); 141178825Sdfr if (tmp == NULL) { 142178825Sdfr *minor_status = ENOMEM; 143178825Sdfr return GSS_S_FAILURE; 144178825Sdfr } 145178825Sdfr memcpy (tmp, 146178825Sdfr input_name_buffer->value, 147178825Sdfr input_name_buffer->length); 148178825Sdfr tmp[input_name_buffer->length] = '\0'; 149178825Sdfr 150178825Sdfr p = strchr (tmp, '@'); 151178825Sdfr if (p != NULL) { 152178825Sdfr *p = '\0'; 153178825Sdfr host = p + 1; 154178825Sdfr } 155178825Sdfr 156233294Sstas kerr = krb5_make_principal(context, &princ, NULL, tmp, host, NULL); 157178825Sdfr free (tmp); 158178825Sdfr *minor_status = kerr; 159178825Sdfr if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) 160178825Sdfr return GSS_S_BAD_NAME; 161233294Sstas else if (kerr) 162233294Sstas return GSS_S_FAILURE; 163178825Sdfr 164233294Sstas krb5_principal_set_type(context, princ, MAGIC_HOSTBASED_NAME_TYPE); 165233294Sstas *output_name = (gss_name_t)princ; 166233294Sstas 167233294Sstas return 0; 168178825Sdfr} 169178825Sdfr 170178825Sdfrstatic OM_uint32 171178825Sdfrimport_export_name (OM_uint32 *minor_status, 172178825Sdfr krb5_context context, 173178825Sdfr const gss_buffer_t input_name_buffer, 174178825Sdfr gss_name_t *output_name) 175178825Sdfr{ 176178825Sdfr unsigned char *p; 177178825Sdfr uint32_t length; 178178825Sdfr OM_uint32 ret; 179178825Sdfr char *name; 180178825Sdfr 181178825Sdfr if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length) 182178825Sdfr return GSS_S_BAD_NAME; 183178825Sdfr 184178825Sdfr /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ 185178825Sdfr 186178825Sdfr p = input_name_buffer->value; 187178825Sdfr 188178825Sdfr if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || 189178825Sdfr p[3] != GSS_KRB5_MECHANISM->length + 2 || 190178825Sdfr p[4] != 0x06 || 191178825Sdfr p[5] != GSS_KRB5_MECHANISM->length || 192233294Sstas memcmp(&p[6], GSS_KRB5_MECHANISM->elements, 193178825Sdfr GSS_KRB5_MECHANISM->length) != 0) 194178825Sdfr return GSS_S_BAD_NAME; 195178825Sdfr 196178825Sdfr p += 6 + GSS_KRB5_MECHANISM->length; 197178825Sdfr 198178825Sdfr length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 199178825Sdfr p += 4; 200178825Sdfr 201178825Sdfr if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length) 202178825Sdfr return GSS_S_BAD_NAME; 203178825Sdfr 204178825Sdfr name = malloc(length + 1); 205178825Sdfr if (name == NULL) { 206178825Sdfr *minor_status = ENOMEM; 207178825Sdfr return GSS_S_FAILURE; 208178825Sdfr } 209178825Sdfr memcpy(name, p, length); 210178825Sdfr name[length] = '\0'; 211178825Sdfr 212178825Sdfr ret = parse_krb5_name(minor_status, context, name, output_name); 213178825Sdfr free(name); 214178825Sdfr 215178825Sdfr return ret; 216178825Sdfr} 217178825Sdfr 218233294SstasOM_uint32 GSSAPI_CALLCONV _gsskrb5_import_name 219178825Sdfr (OM_uint32 * minor_status, 220178825Sdfr const gss_buffer_t input_name_buffer, 221178825Sdfr const gss_OID input_name_type, 222178825Sdfr gss_name_t * output_name 223178825Sdfr ) 224178825Sdfr{ 225178825Sdfr krb5_context context; 226178825Sdfr 227178825Sdfr *minor_status = 0; 228178825Sdfr *output_name = GSS_C_NO_NAME; 229233294Sstas 230178825Sdfr GSSAPI_KRB5_INIT (&context); 231178825Sdfr 232178825Sdfr if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) || 233178825Sdfr gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X)) 234178825Sdfr return import_hostbased_name (minor_status, 235178825Sdfr context, 236178825Sdfr input_name_buffer, 237178825Sdfr output_name); 238233294Sstas else if (input_name_type == GSS_C_NO_OID 239178825Sdfr || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME) 240178825Sdfr || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) 241178825Sdfr /* default printable syntax */ 242178825Sdfr return import_krb5_name (minor_status, 243178825Sdfr context, 244178825Sdfr input_name_buffer, 245178825Sdfr output_name); 246178825Sdfr else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { 247178825Sdfr return import_export_name(minor_status, 248178825Sdfr context, 249233294Sstas input_name_buffer, 250178825Sdfr output_name); 251178825Sdfr } else { 252178825Sdfr *minor_status = 0; 253178825Sdfr return GSS_S_BAD_NAMETYPE; 254178825Sdfr } 255178825Sdfr} 256