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