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