1*5e01956fSGlenn Barry /* 2*5e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 3*5e01956fSGlenn Barry */ 47c478bd9Sstevel@tonic-gate /* 57c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc. 6ab9b2e15Sgtb * 77c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, distribute, and sell this software 87c478bd9Sstevel@tonic-gate * and its documentation for any purpose is hereby granted without fee, 97c478bd9Sstevel@tonic-gate * provided that the above copyright notice appears in all copies and 107c478bd9Sstevel@tonic-gate * that both that copyright notice and this permission notice appear in 117c478bd9Sstevel@tonic-gate * supporting documentation, and that the name of OpenVision not be used 127c478bd9Sstevel@tonic-gate * in advertising or publicity pertaining to distribution of the software 137c478bd9Sstevel@tonic-gate * without specific, written prior permission. OpenVision makes no 147c478bd9Sstevel@tonic-gate * representations about the suitability of this software for any 157c478bd9Sstevel@tonic-gate * purpose. It is provided "as is" without express or implied warranty. 16ab9b2e15Sgtb * 177c478bd9Sstevel@tonic-gate * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 187c478bd9Sstevel@tonic-gate * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 197c478bd9Sstevel@tonic-gate * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 207c478bd9Sstevel@tonic-gate * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 217c478bd9Sstevel@tonic-gate * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 227c478bd9Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 237c478bd9Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 27ab9b2e15Sgtb * $Id: import_name.c 18015 2006-05-17 05:26:12Z raeburn $ 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 30ab9b2e15Sgtb #include "gssapiP_krb5.h" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #ifndef NO_PASSWORD 337c478bd9Sstevel@tonic-gate #include <pwd.h> 34ab9b2e15Sgtb #include <stdio.h> 357c478bd9Sstevel@tonic-gate #endif 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #ifdef HAVE_STRING_H 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #else 407c478bd9Sstevel@tonic-gate #include <strings.h> 417c478bd9Sstevel@tonic-gate #endif 42*5e01956fSGlenn Barry #include <locale.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* 457c478bd9Sstevel@tonic-gate * errors: 467c478bd9Sstevel@tonic-gate * GSS_S_BAD_NAMETYPE if the type is bogus 477c478bd9Sstevel@tonic-gate * GSS_S_BAD_NAME if the type is good but the name is bogus 487c478bd9Sstevel@tonic-gate * GSS_S_FAILURE if memory allocation fails 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate OM_uint32 52ab9b2e15Sgtb krb5_gss_import_name(minor_status, input_name_buffer, 537c478bd9Sstevel@tonic-gate input_name_type, output_name) 547c478bd9Sstevel@tonic-gate OM_uint32 *minor_status; 557c478bd9Sstevel@tonic-gate gss_buffer_t input_name_buffer; 567c478bd9Sstevel@tonic-gate gss_OID input_name_type; 577c478bd9Sstevel@tonic-gate gss_name_t *output_name; 587c478bd9Sstevel@tonic-gate { 597c478bd9Sstevel@tonic-gate krb5_context context; 607c478bd9Sstevel@tonic-gate krb5_principal princ; 617c478bd9Sstevel@tonic-gate krb5_error_code code; 627c478bd9Sstevel@tonic-gate char *stringrep, *tmp, *tmp2, *cp; 637c478bd9Sstevel@tonic-gate OM_uint32 length; 647c478bd9Sstevel@tonic-gate #ifndef NO_PASSWORD 657c478bd9Sstevel@tonic-gate struct passwd *pw; 667c478bd9Sstevel@tonic-gate #endif 677c478bd9Sstevel@tonic-gate 68ab9b2e15Sgtb code = krb5_gss_init_context(&context); 69ab9b2e15Sgtb if (code) { 70ab9b2e15Sgtb *minor_status = code; 71ab9b2e15Sgtb return GSS_S_FAILURE; 72ab9b2e15Sgtb } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* set up default returns */ 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate *output_name = NULL; 777c478bd9Sstevel@tonic-gate *minor_status = 0; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* Go find the appropriate string rep to pass into parse_name */ 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate if ((input_name_type != GSS_C_NULL_OID) && 82ab9b2e15Sgtb (g_OID_equal(input_name_type, gss_nt_service_name) || 837c478bd9Sstevel@tonic-gate g_OID_equal(input_name_type, gss_nt_service_name_v2))) { 847c478bd9Sstevel@tonic-gate char *service, *host; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate if ((tmp = 877c478bd9Sstevel@tonic-gate (char *) xmalloc(input_name_buffer->length + 1)) == NULL) { 887c478bd9Sstevel@tonic-gate *minor_status = ENOMEM; 89ab9b2e15Sgtb krb5_free_context(context); 907c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate memcpy(tmp, input_name_buffer->value, input_name_buffer->length); 947c478bd9Sstevel@tonic-gate tmp[input_name_buffer->length] = 0; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate service = tmp; 97ab9b2e15Sgtb if ((host = strchr(tmp, '@'))) { 987c478bd9Sstevel@tonic-gate *host = '\0'; 997c478bd9Sstevel@tonic-gate host++; 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST, 1037c478bd9Sstevel@tonic-gate &princ); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate xfree(tmp); 1067c478bd9Sstevel@tonic-gate } else if ((input_name_type != GSS_C_NULL_OID) && 1077c478bd9Sstevel@tonic-gate (g_OID_equal(input_name_type, gss_nt_krb5_principal))) { 108*5e01956fSGlenn Barry krb5_principal input; 109*5e01956fSGlenn Barry 110*5e01956fSGlenn Barry if (input_name_buffer->length != sizeof(krb5_principal)) { 111*5e01956fSGlenn Barry *minor_status = (OM_uint32) G_WRONG_SIZE; 112*5e01956fSGlenn Barry /* Solaris Kerberos: spruce-up the err msg */ 113*5e01956fSGlenn Barry krb5_set_error_message(context, *minor_status, 114*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN, 115*5e01956fSGlenn Barry "The size of the specified principal is wrong")); 116*5e01956fSGlenn Barry save_error_info(*minor_status, context); 117*5e01956fSGlenn Barry krb5_free_context(context); 118*5e01956fSGlenn Barry return(GSS_S_BAD_NAME); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate input = *((krb5_principal *) input_name_buffer->value); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if ((code = krb5_copy_principal(context, input, &princ))) { 1247c478bd9Sstevel@tonic-gate *minor_status = code; 125*5e01956fSGlenn Barry save_error_info(*minor_status, context); 126ab9b2e15Sgtb krb5_free_context(context); 1277c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE); 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate } else { 130ab9b2e15Sgtb #ifndef NO_PASSWORD 131ab9b2e15Sgtb uid_t uid; 132ab9b2e15Sgtb struct passwd pwx; 133ab9b2e15Sgtb char pwbuf[BUFSIZ]; 134ab9b2e15Sgtb #endif 135ab9b2e15Sgtb 1367c478bd9Sstevel@tonic-gate stringrep = NULL; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if ((tmp = 1397c478bd9Sstevel@tonic-gate (char *) xmalloc(input_name_buffer->length + 1)) == NULL) { 1407c478bd9Sstevel@tonic-gate *minor_status = ENOMEM; 141ab9b2e15Sgtb krb5_free_context(context); 1427c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate tmp2 = 0; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate memcpy(tmp, input_name_buffer->value, input_name_buffer->length); 1477c478bd9Sstevel@tonic-gate tmp[input_name_buffer->length] = 0; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if ((input_name_type == GSS_C_NULL_OID) || 1507c478bd9Sstevel@tonic-gate g_OID_equal(input_name_type, gss_nt_krb5_name) || 151ab9b2e15Sgtb g_OID_equal(input_name_type, gss_nt_user_name)) { 1527c478bd9Sstevel@tonic-gate stringrep = (char *) tmp; 1537c478bd9Sstevel@tonic-gate #ifndef NO_PASSWORD 154ab9b2e15Sgtb } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) { 155ab9b2e15Sgtb uid = *(uid_t *) input_name_buffer->value; 156ab9b2e15Sgtb do_getpwuid: 157ab9b2e15Sgtb if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0) 158ab9b2e15Sgtb stringrep = pw->pw_name; 1597c478bd9Sstevel@tonic-gate else 1607c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_NOUSER; 161ab9b2e15Sgtb } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) { 162ab9b2e15Sgtb uid = atoi(tmp); 163ab9b2e15Sgtb goto do_getpwuid; 1647c478bd9Sstevel@tonic-gate #endif 1657c478bd9Sstevel@tonic-gate } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) { 1667c478bd9Sstevel@tonic-gate cp = tmp; 1677c478bd9Sstevel@tonic-gate if (*cp++ != 0x04) 1687c478bd9Sstevel@tonic-gate goto fail_name; 1697c478bd9Sstevel@tonic-gate if (*cp++ != 0x01) 1707c478bd9Sstevel@tonic-gate goto fail_name; 1717c478bd9Sstevel@tonic-gate if (*cp++ != 0x00) 1727c478bd9Sstevel@tonic-gate goto fail_name; 1737c478bd9Sstevel@tonic-gate length = *cp++; 1747c478bd9Sstevel@tonic-gate if (length != gss_mech_krb5->length+2) 1757c478bd9Sstevel@tonic-gate goto fail_name; 1767c478bd9Sstevel@tonic-gate if (*cp++ != 0x06) 1777c478bd9Sstevel@tonic-gate goto fail_name; 1787c478bd9Sstevel@tonic-gate length = *cp++; 1797c478bd9Sstevel@tonic-gate if (length != gss_mech_krb5->length) 1807c478bd9Sstevel@tonic-gate goto fail_name; 1817c478bd9Sstevel@tonic-gate if (memcmp(cp, gss_mech_krb5->elements, length) != 0) 1827c478bd9Sstevel@tonic-gate goto fail_name; 1837c478bd9Sstevel@tonic-gate cp += length; 1847c478bd9Sstevel@tonic-gate length = *cp++; 1857c478bd9Sstevel@tonic-gate length = (length << 8) | *cp++; 1867c478bd9Sstevel@tonic-gate length = (length << 8) | *cp++; 1877c478bd9Sstevel@tonic-gate length = (length << 8) | *cp++; 1887c478bd9Sstevel@tonic-gate tmp2 = malloc(length+1); 1897c478bd9Sstevel@tonic-gate if (tmp2 == NULL) { 1907c478bd9Sstevel@tonic-gate xfree(tmp); 1917c478bd9Sstevel@tonic-gate *minor_status = ENOMEM; 192ab9b2e15Sgtb krb5_free_context(context); 1937c478bd9Sstevel@tonic-gate return GSS_S_FAILURE; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate strncpy(tmp2, cp, length); 1967c478bd9Sstevel@tonic-gate tmp2[length] = 0; 197ab9b2e15Sgtb 1987c478bd9Sstevel@tonic-gate stringrep = tmp2; 1997c478bd9Sstevel@tonic-gate } else { 200ab9b2e15Sgtb xfree(tmp); 201ab9b2e15Sgtb krb5_free_context(context); 2027c478bd9Sstevel@tonic-gate return(GSS_S_BAD_NAMETYPE); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* at this point, stringrep is set, or if not, *minor_status is. */ 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (stringrep) 2087c478bd9Sstevel@tonic-gate code = krb5_parse_name(context, (char *) stringrep, &princ); 2097c478bd9Sstevel@tonic-gate else { 2107c478bd9Sstevel@tonic-gate fail_name: 211*5e01956fSGlenn Barry xfree(tmp); 212*5e01956fSGlenn Barry if (tmp2) 2137c478bd9Sstevel@tonic-gate xfree(tmp2); 214*5e01956fSGlenn Barry 215*5e01956fSGlenn Barry /* Solaris Kerberos: spruce-up (not much, sigh) the err msg */ 216*5e01956fSGlenn Barry krb5_set_error_message(context, *minor_status, 217*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN, 218*5e01956fSGlenn Barry "Failed to convert the specified principal to GSS-API internal format")); 219*5e01956fSGlenn Barry save_error_info(*minor_status, context); 220*5e01956fSGlenn Barry 221*5e01956fSGlenn Barry krb5_free_context(context); 222*5e01956fSGlenn Barry return(GSS_S_BAD_NAME); 2237c478bd9Sstevel@tonic-gate } 224ab9b2e15Sgtb 2257c478bd9Sstevel@tonic-gate if (tmp2) 2267c478bd9Sstevel@tonic-gate xfree(tmp2); 2277c478bd9Sstevel@tonic-gate xfree(tmp); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* at this point, a krb5 function has been called to set princ. code 2317c478bd9Sstevel@tonic-gate contains the return status */ 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate if (code) { 234*5e01956fSGlenn Barry /* Solaris Kerberos: spruce-up the err msg */ 235*5e01956fSGlenn Barry *minor_status = (OM_uint32) code; 236*5e01956fSGlenn Barry /* krb5_sname_to_principal() sets specific err msg for bad hostname. */ 237*5e01956fSGlenn Barry if (*minor_status != (OM_uint32)KRB5_ERR_BAD_HOSTNAME) 238*5e01956fSGlenn Barry krb5_set_error_message(context, *minor_status, 239*5e01956fSGlenn Barry dgettext(TEXT_DOMAIN, 240*5e01956fSGlenn Barry "Failed to convert the specified principal to GSS-API internal format: %s"), 241*5e01956fSGlenn Barry error_message(code)); 242*5e01956fSGlenn Barry save_error_info(*minor_status, context); 243*5e01956fSGlenn Barry krb5_free_context(context); 244*5e01956fSGlenn Barry return(GSS_S_BAD_NAME); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* save the name in the validation database */ 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (! kg_save_name((gss_name_t) princ)) { 2507c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ); 251ab9b2e15Sgtb krb5_free_context(context); 2527c478bd9Sstevel@tonic-gate *minor_status = (OM_uint32) G_VALIDATE_FAILED; 2537c478bd9Sstevel@tonic-gate return(GSS_S_FAILURE); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 256ab9b2e15Sgtb krb5_free_context(context); 257ab9b2e15Sgtb 2587c478bd9Sstevel@tonic-gate /* return it */ 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate *output_name = (gss_name_t) princ; 2617c478bd9Sstevel@tonic-gate return(GSS_S_COMPLETE); 2627c478bd9Sstevel@tonic-gate } 263