Home | History | Annotate | Download | only in mech
      1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
      2 
      3 /*
      4  * Copyright 1993 by OpenVision Technologies, Inc.
      5  *
      6  * Permission to use, copy, modify, distribute, and sell this software
      7  * and its documentation for any purpose is hereby granted without fee,
      8  * provided that the above copyright notice appears in all copies and
      9  * that both that copyright notice and this permission notice appear in
     10  * supporting documentation, and that the name of OpenVision not be used
     11  * in advertising or publicity pertaining to distribution of the software
     12  * without specific, written prior permission. OpenVision makes no
     13  * representations about the suitability of this software for any
     14  * purpose.  It is provided "as is" without express or implied warranty.
     15  *
     16  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     18  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
     20  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     21  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     22  * PERFORMANCE OF THIS SOFTWARE.
     23  */
     24 
     25 /*
     26  * $Id: import_name.c 18015 2006-05-17 05:26:12Z raeburn $
     27  */
     28 
     29 #include "gssapiP_krb5.h"
     30 
     31 #ifndef NO_PASSWORD
     32 #include <pwd.h>
     33 #include <stdio.h>
     34 #endif
     35 
     36 #ifdef HAVE_STRING_H
     37 #include <string.h>
     38 #else
     39 #include <strings.h>
     40 #endif
     41 
     42 /*
     43  * errors:
     44  * GSS_S_BAD_NAMETYPE	if the type is bogus
     45  * GSS_S_BAD_NAME	if the type is good but the name is bogus
     46  * GSS_S_FAILURE	if memory allocation fails
     47  */
     48 
     49 OM_uint32
     50 krb5_gss_import_name(minor_status, input_name_buffer,
     51 		     input_name_type, output_name)
     52      OM_uint32 *minor_status;
     53      gss_buffer_t input_name_buffer;
     54      gss_OID input_name_type;
     55      gss_name_t *output_name;
     56 {
     57    krb5_context context;
     58    krb5_principal princ;
     59    krb5_error_code code;
     60    char *stringrep, *tmp, *tmp2, *cp;
     61    OM_uint32	length;
     62 #ifndef NO_PASSWORD
     63    struct passwd *pw;
     64 #endif
     65 
     66    code = krb5_gss_init_context(&context);
     67    if (code) {
     68        *minor_status = code;
     69        return GSS_S_FAILURE;
     70    }
     71 
     72    /* set up default returns */
     73 
     74    *output_name = NULL;
     75    *minor_status = 0;
     76 
     77    /* Go find the appropriate string rep to pass into parse_name */
     78 
     79    if ((input_name_type != GSS_C_NULL_OID) &&
     80        (g_OID_equal(input_name_type, gss_nt_service_name) ||
     81 	g_OID_equal(input_name_type, gss_nt_service_name_v2))) {
     82       char *service, *host;
     83 
     84       if ((tmp =
     85 	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
     86 	 *minor_status = ENOMEM;
     87 	 krb5_free_context(context);
     88 	 return(GSS_S_FAILURE);
     89       }
     90 
     91       memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
     92       tmp[input_name_buffer->length] = 0;
     93 
     94       service = tmp;
     95       if ((host = strchr(tmp, '@'))) {
     96 	 *host = '\0';
     97 	 host++;
     98       }
     99 
    100       code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST,
    101 				     &princ);
    102 
    103       xfree(tmp);
    104    } else if ((input_name_type != GSS_C_NULL_OID) &&
    105 	      (g_OID_equal(input_name_type, gss_nt_krb5_principal))) {
    106       krb5_principal input;
    107 
    108       if (input_name_buffer->length != sizeof(krb5_principal)) {
    109 	 *minor_status = (OM_uint32) G_WRONG_SIZE;
    110 	 krb5_free_context(context);
    111 	 return(GSS_S_BAD_NAME);
    112       }
    113 
    114       input = *((krb5_principal *) input_name_buffer->value);
    115 
    116       if ((code = krb5_copy_principal(context, input, &princ))) {
    117 	 *minor_status = code;
    118 	 krb5_free_context(context);
    119 	 return(GSS_S_FAILURE);
    120       }
    121    } else {
    122 #ifndef NO_PASSWORD
    123       uid_t uid;
    124       struct passwd pwx;
    125       char pwbuf[BUFSIZ];
    126 #endif
    127 
    128       stringrep = NULL;
    129 
    130       if ((tmp =
    131 	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
    132 	 *minor_status = ENOMEM;
    133 	 krb5_free_context(context);
    134 	 return(GSS_S_FAILURE);
    135       }
    136       tmp2 = 0;
    137 
    138       memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
    139       tmp[input_name_buffer->length] = 0;
    140 
    141       if ((input_name_type == GSS_C_NULL_OID) ||
    142 	  g_OID_equal(input_name_type, gss_nt_krb5_name) ||
    143 	  g_OID_equal(input_name_type, gss_nt_user_name)) {
    144 	 stringrep = (char *) tmp;
    145 #ifndef NO_PASSWORD
    146       } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) {
    147 	 uid = *(uid_t *) input_name_buffer->value;
    148       do_getpwuid:
    149 	 if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0)
    150 	     stringrep = pw->pw_name;
    151 	 else
    152 	    *minor_status = (OM_uint32) G_NOUSER;
    153       } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) {
    154 	 uid = atoi(tmp);
    155 	 goto do_getpwuid;
    156 #endif
    157       } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) {
    158 	 cp = tmp;
    159 	 if (*cp++ != 0x04)
    160 		 goto fail_name;
    161 	 if (*cp++ != 0x01)
    162 		 goto fail_name;
    163 	 if (*cp++ != 0x00)
    164 		 goto fail_name;
    165 	 length = *cp++;
    166 	 if (length != gss_mech_krb5->length+2)
    167 		 goto fail_name;
    168 	 if (*cp++ != 0x06)
    169 		 goto fail_name;
    170 	 length = *cp++;
    171 	 if (length != gss_mech_krb5->length)
    172 		 goto fail_name;
    173 	 if (memcmp(cp, gss_mech_krb5->elements, length) != 0)
    174 		 goto fail_name;
    175 	 cp += length;
    176 	 length = *cp++;
    177 	 length = (length << 8) | *cp++;
    178 	 length = (length << 8) | *cp++;
    179 	 length = (length << 8) | *cp++;
    180 	 tmp2 = malloc(length+1);
    181 	 if (tmp2 == NULL) {
    182 		 xfree(tmp);
    183 		 *minor_status = ENOMEM;
    184 		 krb5_free_context(context);
    185 		 return GSS_S_FAILURE;
    186 	 }
    187 	 strncpy(tmp2, cp, length);
    188 	 tmp2[length] = 0;
    189 
    190 	 stringrep = tmp2;
    191      } else {
    192 	 xfree(tmp);
    193 	 krb5_free_context(context);
    194 	 return(GSS_S_BAD_NAMETYPE);
    195       }
    196 
    197       /* at this point, stringrep is set, or if not, *minor_status is. */
    198 
    199       if (stringrep)
    200 	 code = krb5_parse_name(context, (char *) stringrep, &princ);
    201       else {
    202       fail_name:
    203 	 xfree(tmp);
    204 	 if (tmp2)
    205 		 xfree(tmp2);
    206 	 krb5_free_context(context);
    207 	 return(GSS_S_BAD_NAME);
    208       }
    209 
    210       if (tmp2)
    211 	      xfree(tmp2);
    212       xfree(tmp);
    213    }
    214 
    215    /* at this point, a krb5 function has been called to set princ.  code
    216       contains the return status */
    217 
    218    if (code) {
    219       *minor_status = (OM_uint32) code;
    220       krb5_free_context(context);
    221       return(GSS_S_BAD_NAME);
    222    }
    223 
    224    /* save the name in the validation database */
    225 
    226    if (! kg_save_name((gss_name_t) princ)) {
    227       krb5_free_principal(context, princ);
    228       krb5_free_context(context);
    229       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
    230       return(GSS_S_FAILURE);
    231    }
    232 
    233    krb5_free_context(context);
    234 
    235    /* return it */
    236 
    237    *output_name = (gss_name_t) princ;
    238    return(GSS_S_COMPLETE);
    239 }
    240