Home | History | Annotate | Line # | Download | only in krb5
      1 /*	$NetBSD: import_name.c,v 1.2 2017/01/28 21:31:46 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 - 2003 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "gsskrb5_locl.h"
     37 
     38 static OM_uint32
     39 parse_krb5_name (OM_uint32 *minor_status,
     40 		 krb5_context context,
     41 		 const char *name,
     42 		 gss_name_t *output_name)
     43 {
     44     krb5_principal princ;
     45     krb5_error_code kerr;
     46 
     47     kerr = krb5_parse_name (context, name, &princ);
     48 
     49     if (kerr == 0) {
     50 	*output_name = (gss_name_t)princ;
     51 	return GSS_S_COMPLETE;
     52     }
     53     *minor_status = kerr;
     54 
     55     if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
     56 	return GSS_S_BAD_NAME;
     57 
     58     return GSS_S_FAILURE;
     59 }
     60 
     61 static OM_uint32
     62 import_krb5_name (OM_uint32 *minor_status,
     63 		  krb5_context context,
     64 		  const gss_buffer_t input_name_buffer,
     65 		  gss_name_t *output_name)
     66 {
     67     OM_uint32 ret;
     68     char *tmp;
     69 
     70     tmp = malloc (input_name_buffer->length + 1);
     71     if (tmp == NULL) {
     72 	*minor_status = ENOMEM;
     73 	return GSS_S_FAILURE;
     74     }
     75     memcpy (tmp,
     76 	    input_name_buffer->value,
     77 	    input_name_buffer->length);
     78     tmp[input_name_buffer->length] = '\0';
     79 
     80     ret = parse_krb5_name(minor_status, context, tmp, output_name);
     81     free(tmp);
     82 
     83     return ret;
     84 }
     85 
     86 OM_uint32
     87 _gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context,
     88 		    gss_const_name_t targetname, krb5_principal *out)
     89 {
     90     krb5_const_principal p = (krb5_const_principal)targetname;
     91     krb5_error_code ret;
     92     char *hostname = NULL, *service;
     93     int type;
     94     const char *comp;
     95 
     96     *minor_status = 0;
     97 
     98     /* If its not a hostname */
     99     type = krb5_principal_get_type(context, p);
    100     comp = krb5_principal_get_comp_string(context, p, 0);
    101     if (type == KRB5_NT_SRV_HST || type == KRB5_NT_SRV_HST_NEEDS_CANON ||
    102 	(type == KRB5_NT_UNKNOWN && comp != NULL && strcmp(comp, "host") == 0)) {
    103 	if (p->name.name_string.len == 0)
    104 	    return GSS_S_BAD_NAME;
    105 	else if (p->name.name_string.len > 1)
    106 	    hostname = p->name.name_string.val[1];
    107 
    108 	service = p->name.name_string.val[0];
    109 
    110 	ret = krb5_sname_to_principal(context,
    111 				      hostname,
    112 				      service,
    113 				      KRB5_NT_SRV_HST,
    114 				      out);
    115     } else {
    116 	ret = krb5_copy_principal(context, p, out);
    117     }
    118 
    119     if (ret) {
    120 	*minor_status = ret;
    121 	return GSS_S_FAILURE;
    122     }
    123 
    124     return 0;
    125 }
    126 
    127 
    128 static OM_uint32
    129 import_hostbased_name(OM_uint32 *minor_status,
    130 		      krb5_context context,
    131 		      const gss_buffer_t input_name_buffer,
    132 		      gss_name_t *output_name)
    133 {
    134     krb5_principal princ = NULL;
    135     krb5_error_code kerr;
    136     char *tmp, *p, *host = NULL;
    137 
    138     tmp = malloc (input_name_buffer->length + 1);
    139     if (tmp == NULL) {
    140 	*minor_status = ENOMEM;
    141 	return GSS_S_FAILURE;
    142     }
    143     memcpy (tmp,
    144 	    input_name_buffer->value,
    145 	    input_name_buffer->length);
    146     tmp[input_name_buffer->length] = '\0';
    147 
    148     p = strchr (tmp, '@');
    149     if (p != NULL) {
    150 	*p = '\0';
    151 	host = p + 1;
    152     }
    153 
    154     kerr = krb5_make_principal(context, &princ, "", tmp, host, NULL);
    155     free (tmp);
    156     *minor_status = kerr;
    157     if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED)
    158 	return GSS_S_BAD_NAME;
    159     else if (kerr)
    160 	return GSS_S_FAILURE;
    161 
    162     krb5_principal_set_type(context, princ, KRB5_NT_SRV_HST);
    163     *output_name = (gss_name_t)princ;
    164 
    165     return 0;
    166 }
    167 
    168 static OM_uint32
    169 import_export_name (OM_uint32 *minor_status,
    170 		    krb5_context context,
    171 		    const gss_buffer_t input_name_buffer,
    172 		    gss_name_t *output_name)
    173 {
    174     unsigned char *p;
    175     uint32_t length;
    176     OM_uint32 ret;
    177     char *name;
    178 
    179     if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length)
    180 	return GSS_S_BAD_NAME;
    181 
    182     /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
    183 
    184     p = input_name_buffer->value;
    185 
    186     if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 ||
    187 	p[3] != GSS_KRB5_MECHANISM->length + 2 ||
    188 	p[4] != 0x06 ||
    189 	p[5] != GSS_KRB5_MECHANISM->length ||
    190 	memcmp(&p[6], GSS_KRB5_MECHANISM->elements,
    191 	       GSS_KRB5_MECHANISM->length) != 0)
    192 	return GSS_S_BAD_NAME;
    193 
    194     p += 6 + GSS_KRB5_MECHANISM->length;
    195 
    196     length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
    197     p += 4;
    198 
    199     if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length)
    200 	return GSS_S_BAD_NAME;
    201 
    202     name = malloc(length + 1);
    203     if (name == NULL) {
    204 	*minor_status = ENOMEM;
    205 	return GSS_S_FAILURE;
    206     }
    207     memcpy(name, p, length);
    208     name[length] = '\0';
    209 
    210     ret = parse_krb5_name(minor_status, context, name, output_name);
    211     free(name);
    212 
    213     return ret;
    214 }
    215 
    216 OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_name
    217            (OM_uint32 * minor_status,
    218             const gss_buffer_t input_name_buffer,
    219             const gss_OID input_name_type,
    220             gss_name_t * output_name
    221            )
    222 {
    223     krb5_context context;
    224 
    225     *minor_status = 0;
    226     *output_name = GSS_C_NO_NAME;
    227 
    228     GSSAPI_KRB5_INIT (&context);
    229 
    230     if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) ||
    231 	gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X))
    232 	return import_hostbased_name (minor_status,
    233 				      context,
    234 				      input_name_buffer,
    235 				      output_name);
    236     else if (input_name_type == GSS_C_NO_OID
    237 	     || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME)
    238 	     || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME))
    239  	/* default printable syntax */
    240 	return import_krb5_name (minor_status,
    241 				 context,
    242 				 input_name_buffer,
    243 				 output_name);
    244     else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
    245 	return import_export_name(minor_status,
    246 				  context,
    247 				  input_name_buffer,
    248 				  output_name);
    249     } else {
    250 	*minor_status = 0;
    251 	return GSS_S_BAD_NAMETYPE;
    252     }
    253 }
    254