-: 0:Source:import_name.c -: 0:Graph:/var/tsitkova/Sources/v10/trunk/src/lib/gssapi/krb5/import_name.so.gcno -: 0:Data:/var/tsitkova/Sources/v10/trunk/src/lib/gssapi/krb5/import_name.so.gcda -: 0:Runs:1069 -: 0:Programs:1 -: 1:/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -: 2:/* -: 3: * Copyright 1993 by OpenVision Technologies, Inc. -: 4: * -: 5: * Permission to use, copy, modify, distribute, and sell this software -: 6: * and its documentation for any purpose is hereby granted without fee, -: 7: * provided that the above copyright notice appears in all copies and -: 8: * that both that copyright notice and this permission notice appear in -: 9: * supporting documentation, and that the name of OpenVision not be used -: 10: * in advertising or publicity pertaining to distribution of the software -: 11: * without specific, written prior permission. OpenVision makes no -: 12: * representations about the suitability of this software for any -: 13: * purpose. It is provided "as is" without express or implied warranty. -: 14: * -: 15: * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -: 16: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -: 17: * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR -: 18: * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -: 19: * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -: 20: * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -: 21: * PERFORMANCE OF THIS SOFTWARE. -: 22: */ -: 23: -: 24:/* -: 25: * $Id: import_name.c 25144 2011-09-04 23:52:34Z raeburn $ -: 26: */ -: 27: -: 28:#include "gssapiP_krb5.h" -: 29: -: 30:#ifndef NO_PASSWORD -: 31:#include -: 32:#include -: 33:#endif -: 34: -: 35:#ifdef HAVE_STRING_H -: 36:#include -: 37:#else -: 38:#include -: 39:#endif -: 40: -: 41:/* -: 42: * errors: -: 43: * GSS_S_BAD_NAMETYPE if the type is bogus -: 44: * GSS_S_BAD_NAME if the type is good but the name is bogus -: 45: * GSS_S_FAILURE if memory allocation fails -: 46: */ -: 47: -: 48:/* -: 49: * Import serialized authdata context -: 50: */ -: 51:static krb5_error_code #####: 52:import_name_composite(krb5_context context, -: 53: unsigned char *enc_data, size_t enc_length, -: 54: krb5_authdata_context *pad_context) -: 55:{ -: 56: krb5_authdata_context ad_context; -: 57: krb5_error_code code; -: 58: krb5_data data; -: 59: #####: 60: code = krb5_authdata_context_init(context, &ad_context); #####: 61: if (code != 0) #####: 62: return code; -: 63: #####: 64: data.data = (char *)enc_data; #####: 65: data.length = enc_length; -: 66: #####: 67: code = krb5_authdata_import_attributes(context, -: 68: ad_context, -: 69: AD_USAGE_MASK, -: 70: &data); #####: 71: if (code != 0) { #####: 72: krb5_authdata_context_free(context, ad_context); #####: 73: return code; -: 74: } -: 75: #####: 76: *pad_context = ad_context; -: 77: #####: 78: return 0; -: 79:} -: 80: -: 81:/* Split a host-based name "service[@host]" into allocated strings -: 82: * placed in *service_out and *host_out (possibly NULL). */ -: 83:static krb5_error_code 174: 84:parse_hostbased(const char *str, size_t len, -: 85: char **service_out, char **host_out) -: 86:{ -: 87: const char *at; -: 88: size_t servicelen, hostlen; 174: 89: char *service, *host = NULL; -: 90: 174: 91: *service_out = *host_out = NULL; -: 92: -: 93: /* Find the bound of the service name and copy it. */ 174: 94: at = memchr(str, '@', len); 174: 95: servicelen = (at == NULL) ? len : (size_t)(at - str); 174: 96: service = xmalloc(servicelen + 1); 174: 97: if (service == NULL) #####: 98: return ENOMEM; 174: 99: memcpy(service, str, servicelen); 174: 100: service[servicelen] = '\0'; -: 101: -: 102: /* If present, copy the hostname. */ 174: 103: if (at != NULL) { 28: 104: hostlen = len - servicelen - 1; 28: 105: host = malloc(hostlen + 1); 28: 106: if (host == NULL) { #####: 107: free(service); #####: 108: return ENOMEM; -: 109: } 28: 110: memcpy(host, at + 1, hostlen); 28: 111: host[hostlen] = '\0'; -: 112: } -: 113: 174: 114: *service_out = service; 174: 115: *host_out = host; 174: 116: return 0; -: 117:} -: 118: -: 119:OM_uint32 KRB5_CALLCONV 1229: 120:krb5_gss_import_name(minor_status, input_name_buffer, -: 121: input_name_type, output_name) -: 122: OM_uint32 *minor_status; -: 123: gss_buffer_t input_name_buffer; -: 124: gss_OID input_name_type; -: 125: gss_name_t *output_name; -: 126:{ -: 127: krb5_context context; 1229: 128: krb5_principal princ = NULL; -: 129: krb5_error_code code; -: 130: unsigned char *cp, *end; 1229: 131: char *tmp = NULL, *tmp2 = NULL, *service = NULL, *host = NULL, *stringrep; -: 132: ssize_t length; -: 133:#ifndef NO_PASSWORD -: 134: struct passwd *pw; -: 135:#endif 1229: 136: int has_ad = 0; 1229: 137: krb5_authdata_context ad_context = NULL; 1229: 138: OM_uint32 status = GSS_S_FAILURE; -: 139: krb5_gss_name_t name; -: 140: 1229: 141: *output_name = NULL; 1229: 142: *minor_status = 0; -: 143: 1229: 144: code = krb5_gss_init_context(&context); 1229: 145: if (code) #####: 146: goto cleanup; -: 147: 4916: 148: if ((input_name_type != GSS_C_NULL_OID) && 2458: 149: (g_OID_equal(input_name_type, gss_nt_service_name) || 1055: 150: g_OID_equal(input_name_type, gss_nt_service_name_v2))) { -: 151: /* Split the name into service and host (or NULL). */ 174: 152: code = parse_hostbased(input_name_buffer->value, -: 153: input_name_buffer->length, &service, &host); 174: 154: if (code) #####: 155: goto cleanup; -: 156: -: 157: /* -: 158: * Compute the initiator target name. In some cases this is a waste of -: 159: * getaddrinfo/getnameinfo queries, but computing the name when we need -: 160: * it would require a lot of code changes. -: 161: */ 174: 162: code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST, -: 163: &princ); 174: 164: if (code) #####: 165: goto cleanup; 3165: 166: } else if ((input_name_type != GSS_C_NULL_OID) && 2110: 167: (g_OID_equal(input_name_type, gss_nt_krb5_principal))) { -: 168: krb5_principal input; -: 169: #####: 170: if (input_name_buffer->length != sizeof(krb5_principal)) { #####: 171: code = G_WRONG_SIZE; #####: 172: status = GSS_S_BAD_NAME; #####: 173: goto cleanup; -: 174: } -: 175: #####: 176: input = *((krb5_principal *) input_name_buffer->value); -: 177: #####: 178: code = krb5_copy_principal(context, input, &princ); #####: 179: if (code) #####: 180: goto cleanup; 2110: 181: } else if ((input_name_type != NULL) && 1055: 182: g_OID_equal(input_name_type, GSS_C_NT_ANONYMOUS)) { #####: 183: code = krb5_copy_principal(context, krb5_anonymous_principal(), -: 184: &princ); #####: 185: if (code) #####: 186: goto cleanup; -: 187: } else { -: 188:#ifndef NO_PASSWORD -: 189: uid_t uid; -: 190: struct passwd pwx; -: 191: char pwbuf[BUFSIZ]; -: 192:#endif -: 193: 1055: 194: stringrep = NULL; -: 195: 1055: 196: tmp = k5alloc(input_name_buffer->length + 1, &code); 1055: 197: if (tmp == NULL) #####: 198: goto cleanup; 1055: 199: tmp2 = NULL; -: 200: 1055: 201: memcpy(tmp, input_name_buffer->value, input_name_buffer->length); 1055: 202: tmp[input_name_buffer->length] = '\0'; -: 203: -: 204: /* Find the appropriate string rep to pass into parse_name. */ 4304: 205: if ((input_name_type == GSS_C_NULL_OID) || 2110: 206: g_OID_equal(input_name_type, gss_nt_krb5_name) || 84: 207: g_OID_equal(input_name_type, gss_nt_user_name)) { 1055: 208: stringrep = (char *) tmp; -: 209:#ifndef NO_PASSWORD #####: 210: } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) { #####: 211: uid = *(uid_t *) input_name_buffer->value; -: 212: do_getpwuid: #####: 213: if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0) #####: 214: stringrep = pw->pw_name; -: 215: else #####: 216: code = G_NOUSER; #####: 217: } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) { #####: 218: uid = atoi(tmp); #####: 219: goto do_getpwuid; -: 220:#endif #####: 221: } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) { -: 222:#define BOUNDS_CHECK(cp, end, n) \ -: 223: do { if ((end) - (cp) < (n)) goto fail_name; } while (0) #####: 224: cp = (unsigned char *)tmp; #####: 225: end = cp + input_name_buffer->length; -: 226: #####: 227: BOUNDS_CHECK(cp, end, 2); #####: 228: if (*cp++ != 0x04) #####: 229: goto fail_name; #####: 230: switch (*cp++) { -: 231: case 0x01: #####: 232: break; -: 233: case 0x02: #####: 234: has_ad++; #####: 235: break; -: 236: default: #####: 237: goto fail_name; -: 238: } -: 239: #####: 240: BOUNDS_CHECK(cp, end, 2); #####: 241: if (*cp++ != 0x00) #####: 242: goto fail_name; #####: 243: length = *cp++; #####: 244: if (length != (ssize_t)gss_mech_krb5->length+2) #####: 245: goto fail_name; -: 246: #####: 247: BOUNDS_CHECK(cp, end, 2); #####: 248: if (*cp++ != 0x06) #####: 249: goto fail_name; #####: 250: length = *cp++; #####: 251: if (length != (ssize_t)gss_mech_krb5->length) #####: 252: goto fail_name; -: 253: #####: 254: BOUNDS_CHECK(cp, end, length); #####: 255: if (memcmp(cp, gss_mech_krb5->elements, length) != 0) #####: 256: goto fail_name; #####: 257: cp += length; -: 258: #####: 259: BOUNDS_CHECK(cp, end, 4); #####: 260: length = *cp++; #####: 261: length = (length << 8) | *cp++; #####: 262: length = (length << 8) | *cp++; #####: 263: length = (length << 8) | *cp++; -: 264: #####: 265: BOUNDS_CHECK(cp, end, length); #####: 266: tmp2 = k5alloc(length + 1, &code); #####: 267: if (tmp2 == NULL) #####: 268: goto cleanup; #####: 269: strncpy(tmp2, (char *)cp, length); #####: 270: tmp2[length] = 0; #####: 271: stringrep = tmp2; #####: 272: cp += length; -: 273: #####: 274: if (has_ad) { #####: 275: BOUNDS_CHECK(cp, end, 4); #####: 276: length = *cp++; #####: 277: length = (length << 8) | *cp++; #####: 278: length = (length << 8) | *cp++; #####: 279: length = (length << 8) | *cp++; -: 280: #####: 281: BOUNDS_CHECK(cp, end, length); #####: 282: code = import_name_composite(context, -: 283: cp, length, -: 284: &ad_context); #####: 285: if (code != 0) #####: 286: goto fail_name; #####: 287: cp += length; -: 288: } #####: 289: assert(cp == end); -: 290: } else { #####: 291: status = GSS_S_BAD_NAMETYPE; #####: 292: goto cleanup; -: 293: } -: 294: -: 295: /* At this point, stringrep is set, or if not, code is. */ 1055: 296: if (stringrep) { 1055: 297: code = krb5_parse_name(context, (char *)stringrep, &princ); 1055: 298: if (code) #####: 299: goto cleanup; -: 300: } else { -: 301: fail_name: #####: 302: status = GSS_S_BAD_NAME; #####: 303: goto cleanup; -: 304: } -: 305: } -: 306: -: 307: /* Create a name and save it in the validation database. */ 1229: 308: code = kg_init_name(context, princ, service, host, ad_context, -: 309: KG_INIT_NAME_NO_COPY, &name); 1229: 310: if (code) #####: 311: goto cleanup; 1229: 312: princ = NULL; 1229: 313: ad_context = NULL; 1229: 314: service = host = NULL; 1229: 315: *output_name = (gss_name_t)name; 1229: 316: status = GSS_S_COMPLETE; -: 317: -: 318:cleanup: 1229: 319: *minor_status = (OM_uint32)code; 1229: 320: if (*minor_status) #####: 321: save_error_info(*minor_status, context); 1229: 322: krb5_free_principal(context, princ); 1229: 323: krb5_authdata_context_free(context, ad_context); 1229: 324: krb5_free_context(context); 1229: 325: free(tmp); 1229: 326: free(tmp2); 1229: 327: free(service); 1229: 328: free(host); 1229: 329: return status; -: 330:}