17c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27c478bd9Sstevel@tonic-gate 
37c478bd9Sstevel@tonic-gate /*
47c478bd9Sstevel@tonic-gate  * Copyright 1993 by OpenVision Technologies, Inc.
5*ab9b2e15Sgtb  *
67c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, distribute, and sell this software
77c478bd9Sstevel@tonic-gate  * and its documentation for any purpose is hereby granted without fee,
87c478bd9Sstevel@tonic-gate  * provided that the above copyright notice appears in all copies and
97c478bd9Sstevel@tonic-gate  * that both that copyright notice and this permission notice appear in
107c478bd9Sstevel@tonic-gate  * supporting documentation, and that the name of OpenVision not be used
117c478bd9Sstevel@tonic-gate  * in advertising or publicity pertaining to distribution of the software
127c478bd9Sstevel@tonic-gate  * without specific, written prior permission. OpenVision makes no
137c478bd9Sstevel@tonic-gate  * representations about the suitability of this software for any
147c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
15*ab9b2e15Sgtb  *
167c478bd9Sstevel@tonic-gate  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
177c478bd9Sstevel@tonic-gate  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
187c478bd9Sstevel@tonic-gate  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
197c478bd9Sstevel@tonic-gate  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
207c478bd9Sstevel@tonic-gate  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
217c478bd9Sstevel@tonic-gate  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
227c478bd9Sstevel@tonic-gate  * PERFORMANCE OF THIS SOFTWARE.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
26*ab9b2e15Sgtb  * $Id: import_name.c 18015 2006-05-17 05:26:12Z raeburn $
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
29*ab9b2e15Sgtb #include "gssapiP_krb5.h"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #ifndef NO_PASSWORD
327c478bd9Sstevel@tonic-gate #include <pwd.h>
33*ab9b2e15Sgtb #include <stdio.h>
347c478bd9Sstevel@tonic-gate #endif
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #ifdef HAVE_STRING_H
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #else
397c478bd9Sstevel@tonic-gate #include <strings.h>
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /*
437c478bd9Sstevel@tonic-gate  * errors:
447c478bd9Sstevel@tonic-gate  * GSS_S_BAD_NAMETYPE	if the type is bogus
457c478bd9Sstevel@tonic-gate  * GSS_S_BAD_NAME	if the type is good but the name is bogus
467c478bd9Sstevel@tonic-gate  * GSS_S_FAILURE	if memory allocation fails
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate OM_uint32
50*ab9b2e15Sgtb krb5_gss_import_name(minor_status, input_name_buffer,
517c478bd9Sstevel@tonic-gate 		     input_name_type, output_name)
527c478bd9Sstevel@tonic-gate      OM_uint32 *minor_status;
537c478bd9Sstevel@tonic-gate      gss_buffer_t input_name_buffer;
547c478bd9Sstevel@tonic-gate      gss_OID input_name_type;
557c478bd9Sstevel@tonic-gate      gss_name_t *output_name;
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate    krb5_context context;
587c478bd9Sstevel@tonic-gate    krb5_principal princ;
597c478bd9Sstevel@tonic-gate    krb5_error_code code;
607c478bd9Sstevel@tonic-gate    char *stringrep, *tmp, *tmp2, *cp;
617c478bd9Sstevel@tonic-gate    OM_uint32	length;
627c478bd9Sstevel@tonic-gate #ifndef NO_PASSWORD
637c478bd9Sstevel@tonic-gate    struct passwd *pw;
647c478bd9Sstevel@tonic-gate #endif
657c478bd9Sstevel@tonic-gate 
66*ab9b2e15Sgtb    code = krb5_gss_init_context(&context);
67*ab9b2e15Sgtb    if (code) {
68*ab9b2e15Sgtb        *minor_status = code;
69*ab9b2e15Sgtb        return GSS_S_FAILURE;
70*ab9b2e15Sgtb    }
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate    /* set up default returns */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate    *output_name = NULL;
757c478bd9Sstevel@tonic-gate    *minor_status = 0;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate    /* Go find the appropriate string rep to pass into parse_name */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate    if ((input_name_type != GSS_C_NULL_OID) &&
80*ab9b2e15Sgtb        (g_OID_equal(input_name_type, gss_nt_service_name) ||
817c478bd9Sstevel@tonic-gate 	g_OID_equal(input_name_type, gss_nt_service_name_v2))) {
827c478bd9Sstevel@tonic-gate       char *service, *host;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate       if ((tmp =
857c478bd9Sstevel@tonic-gate 	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
867c478bd9Sstevel@tonic-gate 	 *minor_status = ENOMEM;
87*ab9b2e15Sgtb 	 krb5_free_context(context);
887c478bd9Sstevel@tonic-gate 	 return(GSS_S_FAILURE);
897c478bd9Sstevel@tonic-gate       }
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate       memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
927c478bd9Sstevel@tonic-gate       tmp[input_name_buffer->length] = 0;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate       service = tmp;
95*ab9b2e15Sgtb       if ((host = strchr(tmp, '@'))) {
967c478bd9Sstevel@tonic-gate 	 *host = '\0';
977c478bd9Sstevel@tonic-gate 	 host++;
987c478bd9Sstevel@tonic-gate       }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate       code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST,
1017c478bd9Sstevel@tonic-gate 				     &princ);
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate       xfree(tmp);
1047c478bd9Sstevel@tonic-gate    } else if ((input_name_type != GSS_C_NULL_OID) &&
1057c478bd9Sstevel@tonic-gate 	      (g_OID_equal(input_name_type, gss_nt_krb5_principal))) {
1067c478bd9Sstevel@tonic-gate       krb5_principal input;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate       if (input_name_buffer->length != sizeof(krb5_principal)) {
1097c478bd9Sstevel@tonic-gate 	 *minor_status = (OM_uint32) G_WRONG_SIZE;
110*ab9b2e15Sgtb 	 krb5_free_context(context);
1117c478bd9Sstevel@tonic-gate 	 return(GSS_S_BAD_NAME);
1127c478bd9Sstevel@tonic-gate       }
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate       input = *((krb5_principal *) input_name_buffer->value);
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate       if ((code = krb5_copy_principal(context, input, &princ))) {
1177c478bd9Sstevel@tonic-gate 	 *minor_status = code;
118*ab9b2e15Sgtb 	 krb5_free_context(context);
1197c478bd9Sstevel@tonic-gate 	 return(GSS_S_FAILURE);
1207c478bd9Sstevel@tonic-gate       }
1217c478bd9Sstevel@tonic-gate    } else {
122*ab9b2e15Sgtb #ifndef NO_PASSWORD
123*ab9b2e15Sgtb       uid_t uid;
124*ab9b2e15Sgtb       struct passwd pwx;
125*ab9b2e15Sgtb       char pwbuf[BUFSIZ];
126*ab9b2e15Sgtb #endif
127*ab9b2e15Sgtb 
1287c478bd9Sstevel@tonic-gate       stringrep = NULL;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate       if ((tmp =
1317c478bd9Sstevel@tonic-gate 	   (char *) xmalloc(input_name_buffer->length + 1)) == NULL) {
1327c478bd9Sstevel@tonic-gate 	 *minor_status = ENOMEM;
133*ab9b2e15Sgtb 	 krb5_free_context(context);
1347c478bd9Sstevel@tonic-gate 	 return(GSS_S_FAILURE);
1357c478bd9Sstevel@tonic-gate       }
1367c478bd9Sstevel@tonic-gate       tmp2 = 0;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate       memcpy(tmp, input_name_buffer->value, input_name_buffer->length);
1397c478bd9Sstevel@tonic-gate       tmp[input_name_buffer->length] = 0;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate       if ((input_name_type == GSS_C_NULL_OID) ||
1427c478bd9Sstevel@tonic-gate 	  g_OID_equal(input_name_type, gss_nt_krb5_name) ||
143*ab9b2e15Sgtb 	  g_OID_equal(input_name_type, gss_nt_user_name)) {
1447c478bd9Sstevel@tonic-gate 	 stringrep = (char *) tmp;
1457c478bd9Sstevel@tonic-gate #ifndef NO_PASSWORD
146*ab9b2e15Sgtb       } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) {
147*ab9b2e15Sgtb 	 uid = *(uid_t *) input_name_buffer->value;
148*ab9b2e15Sgtb       do_getpwuid:
149*ab9b2e15Sgtb 	 if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0)
150*ab9b2e15Sgtb 	     stringrep = pw->pw_name;
1517c478bd9Sstevel@tonic-gate 	 else
1527c478bd9Sstevel@tonic-gate 	    *minor_status = (OM_uint32) G_NOUSER;
153*ab9b2e15Sgtb       } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) {
154*ab9b2e15Sgtb 	 uid = atoi(tmp);
155*ab9b2e15Sgtb 	 goto do_getpwuid;
1567c478bd9Sstevel@tonic-gate #endif
1577c478bd9Sstevel@tonic-gate       } else if (g_OID_equal(input_name_type, gss_nt_exported_name)) {
1587c478bd9Sstevel@tonic-gate 	 cp = tmp;
1597c478bd9Sstevel@tonic-gate 	 if (*cp++ != 0x04)
1607c478bd9Sstevel@tonic-gate 		 goto fail_name;
1617c478bd9Sstevel@tonic-gate 	 if (*cp++ != 0x01)
1627c478bd9Sstevel@tonic-gate 		 goto fail_name;
1637c478bd9Sstevel@tonic-gate 	 if (*cp++ != 0x00)
1647c478bd9Sstevel@tonic-gate 		 goto fail_name;
1657c478bd9Sstevel@tonic-gate 	 length = *cp++;
1667c478bd9Sstevel@tonic-gate 	 if (length != gss_mech_krb5->length+2)
1677c478bd9Sstevel@tonic-gate 		 goto fail_name;
1687c478bd9Sstevel@tonic-gate 	 if (*cp++ != 0x06)
1697c478bd9Sstevel@tonic-gate 		 goto fail_name;
1707c478bd9Sstevel@tonic-gate 	 length = *cp++;
1717c478bd9Sstevel@tonic-gate 	 if (length != gss_mech_krb5->length)
1727c478bd9Sstevel@tonic-gate 		 goto fail_name;
1737c478bd9Sstevel@tonic-gate 	 if (memcmp(cp, gss_mech_krb5->elements, length) != 0)
1747c478bd9Sstevel@tonic-gate 		 goto fail_name;
1757c478bd9Sstevel@tonic-gate 	 cp += length;
1767c478bd9Sstevel@tonic-gate 	 length = *cp++;
1777c478bd9Sstevel@tonic-gate 	 length = (length << 8) | *cp++;
1787c478bd9Sstevel@tonic-gate 	 length = (length << 8) | *cp++;
1797c478bd9Sstevel@tonic-gate 	 length = (length << 8) | *cp++;
1807c478bd9Sstevel@tonic-gate 	 tmp2 = malloc(length+1);
1817c478bd9Sstevel@tonic-gate 	 if (tmp2 == NULL) {
1827c478bd9Sstevel@tonic-gate 		 xfree(tmp);
1837c478bd9Sstevel@tonic-gate 		 *minor_status = ENOMEM;
184*ab9b2e15Sgtb 		 krb5_free_context(context);
1857c478bd9Sstevel@tonic-gate 		 return GSS_S_FAILURE;
1867c478bd9Sstevel@tonic-gate 	 }
1877c478bd9Sstevel@tonic-gate 	 strncpy(tmp2, cp, length);
1887c478bd9Sstevel@tonic-gate 	 tmp2[length] = 0;
189*ab9b2e15Sgtb 
1907c478bd9Sstevel@tonic-gate 	 stringrep = tmp2;
1917c478bd9Sstevel@tonic-gate      } else {
192*ab9b2e15Sgtb 	 xfree(tmp);
193*ab9b2e15Sgtb 	 krb5_free_context(context);
1947c478bd9Sstevel@tonic-gate 	 return(GSS_S_BAD_NAMETYPE);
1957c478bd9Sstevel@tonic-gate       }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate       /* at this point, stringrep is set, or if not, *minor_status is. */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate       if (stringrep)
2007c478bd9Sstevel@tonic-gate 	 code = krb5_parse_name(context, (char *) stringrep, &princ);
2017c478bd9Sstevel@tonic-gate       else {
2027c478bd9Sstevel@tonic-gate       fail_name:
2037c478bd9Sstevel@tonic-gate 	 xfree(tmp);
2047c478bd9Sstevel@tonic-gate 	 if (tmp2)
2057c478bd9Sstevel@tonic-gate 		 xfree(tmp2);
206*ab9b2e15Sgtb 	 krb5_free_context(context);
2077c478bd9Sstevel@tonic-gate 	 return(GSS_S_BAD_NAME);
2087c478bd9Sstevel@tonic-gate       }
209*ab9b2e15Sgtb 
2107c478bd9Sstevel@tonic-gate       if (tmp2)
2117c478bd9Sstevel@tonic-gate 	      xfree(tmp2);
2127c478bd9Sstevel@tonic-gate       xfree(tmp);
2137c478bd9Sstevel@tonic-gate    }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate    /* at this point, a krb5 function has been called to set princ.  code
2167c478bd9Sstevel@tonic-gate       contains the return status */
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate    if (code) {
2197c478bd9Sstevel@tonic-gate       *minor_status = (OM_uint32) code;
220*ab9b2e15Sgtb       krb5_free_context(context);
2217c478bd9Sstevel@tonic-gate       return(GSS_S_BAD_NAME);
2227c478bd9Sstevel@tonic-gate    }
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate    /* save the name in the validation database */
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate    if (! kg_save_name((gss_name_t) princ)) {
2277c478bd9Sstevel@tonic-gate       krb5_free_principal(context, princ);
228*ab9b2e15Sgtb       krb5_free_context(context);
2297c478bd9Sstevel@tonic-gate       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
2307c478bd9Sstevel@tonic-gate       return(GSS_S_FAILURE);
2317c478bd9Sstevel@tonic-gate    }
2327c478bd9Sstevel@tonic-gate 
233*ab9b2e15Sgtb    krb5_free_context(context);
234*ab9b2e15Sgtb 
2357c478bd9Sstevel@tonic-gate    /* return it */
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate    *output_name = (gss_name_t) princ;
2387c478bd9Sstevel@tonic-gate    return(GSS_S_COMPLETE);
2397c478bd9Sstevel@tonic-gate }
240