15e01956fSGlenn Barry /*
25e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
35e01956fSGlenn Barry */
47c478bd9Sstevel@tonic-gate /*
57c478bd9Sstevel@tonic-gate * Copyright 1993 by OpenVision Technologies, Inc.
6*55fea89dSDan Cross *
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.
16*55fea89dSDan Cross *
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
425e01956fSGlenn 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
krb5_gss_import_name(minor_status,input_name_buffer,input_name_type,output_name)52*55fea89dSDan Cross 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))) {
1085e01956fSGlenn Barry krb5_principal input;
1095e01956fSGlenn Barry
1105e01956fSGlenn Barry if (input_name_buffer->length != sizeof(krb5_principal)) {
1115e01956fSGlenn Barry *minor_status = (OM_uint32) G_WRONG_SIZE;
1125e01956fSGlenn Barry /* Solaris Kerberos: spruce-up the err msg */
1135e01956fSGlenn Barry krb5_set_error_message(context, *minor_status,
1145e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
1155e01956fSGlenn Barry "The size of the specified principal is wrong"));
1165e01956fSGlenn Barry save_error_info(*minor_status, context);
1175e01956fSGlenn Barry krb5_free_context(context);
1185e01956fSGlenn 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;
1255e01956fSGlenn 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;
197*55fea89dSDan Cross
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:
2115e01956fSGlenn Barry xfree(tmp);
2125e01956fSGlenn Barry if (tmp2)
2137c478bd9Sstevel@tonic-gate xfree(tmp2);
2145e01956fSGlenn Barry
2155e01956fSGlenn Barry /* Solaris Kerberos: spruce-up (not much, sigh) the err msg */
2165e01956fSGlenn Barry krb5_set_error_message(context, *minor_status,
2175e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
2185e01956fSGlenn Barry "Failed to convert the specified principal to GSS-API internal format"));
2195e01956fSGlenn Barry save_error_info(*minor_status, context);
2205e01956fSGlenn Barry
2215e01956fSGlenn Barry krb5_free_context(context);
2225e01956fSGlenn Barry return(GSS_S_BAD_NAME);
2237c478bd9Sstevel@tonic-gate }
224*55fea89dSDan Cross
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) {
2345e01956fSGlenn Barry /* Solaris Kerberos: spruce-up the err msg */
2355e01956fSGlenn Barry *minor_status = (OM_uint32) code;
2365e01956fSGlenn Barry /* krb5_sname_to_principal() sets specific err msg for bad hostname. */
2375e01956fSGlenn Barry if (*minor_status != (OM_uint32)KRB5_ERR_BAD_HOSTNAME)
2385e01956fSGlenn Barry krb5_set_error_message(context, *minor_status,
2395e01956fSGlenn Barry dgettext(TEXT_DOMAIN,
2405e01956fSGlenn Barry "Failed to convert the specified principal to GSS-API internal format: %s"),
2415e01956fSGlenn Barry error_message(code));
2425e01956fSGlenn Barry save_error_info(*minor_status, context);
2435e01956fSGlenn Barry krb5_free_context(context);
2445e01956fSGlenn 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