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