17c478bd9Sstevel@tonic-gate /*
2159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*48bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
57c478bd9Sstevel@tonic-gate  */
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate  * lib/krb5/os/kuserok.c
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * Copyright 1990,1993 by the Massachusetts Institute of Technology.
127c478bd9Sstevel@tonic-gate  * All Rights Reserved.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
157c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
167c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
177c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
18*48bbca81SDaniel Hoffman  *
197c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
207c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
217c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
227c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
237c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
247c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
257c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
26159d09a2SMark Phalan  * permission.  Furthermore if you modify this software you must label
27159d09a2SMark Phalan  * your software as modified software and not distribute it in such a
28159d09a2SMark Phalan  * fashion that it might be confused with the original M.I.T. software.
29159d09a2SMark Phalan  * M.I.T. makes no representations about the suitability of
307c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
317c478bd9Sstevel@tonic-gate  * or implied warranty.
32*48bbca81SDaniel Hoffman  *
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * krb5_kuserok()
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include "k5-int.h"
38159d09a2SMark Phalan #if !defined(_WIN32)		/* Not yet for Windows */
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <string.h>
417c478bd9Sstevel@tonic-gate #include <stdlib.h>
427c478bd9Sstevel@tonic-gate #include <pwd.h>
437c478bd9Sstevel@tonic-gate #include <libintl.h>
447c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h>
457c478bd9Sstevel@tonic-gate #include <gssapi/gssapi_ext.h>
467c478bd9Sstevel@tonic-gate #include <gssapi_krb5.h>
477c478bd9Sstevel@tonic-gate #include <gssapiP_krb5.h>
487c478bd9Sstevel@tonic-gate #include <syslog.h>
497c478bd9Sstevel@tonic-gate 
50159d09a2SMark Phalan #if defined(_AIX) && defined(_IBMR2)
51159d09a2SMark Phalan #include <sys/access.h>
52159d09a2SMark Phalan /* xlc has a bug with "const" */
53159d09a2SMark Phalan #define getpwnam(user) getpwnam((char *)user)
54159d09a2SMark Phalan #endif
55159d09a2SMark Phalan 
56159d09a2SMark Phalan #define MAX_USERNAME 65
57159d09a2SMark Phalan #define	CACHE_FILENAME_LEN 35
58159d09a2SMark Phalan 
59159d09a2SMark Phalan #if defined(__APPLE__) && defined(__MACH__)
60159d09a2SMark Phalan #include <hfs/hfs_mount.h>	/* XXX */
61159d09a2SMark Phalan #define FILE_OWNER_OK(UID)  ((UID) == 0 || (UID) == UNKNOWNUID)
62159d09a2SMark Phalan #else
63159d09a2SMark Phalan #define FILE_OWNER_OK(UID)  ((UID) == 0)
64159d09a2SMark Phalan #endif
65159d09a2SMark Phalan 
66159d09a2SMark Phalan /* Solaris Kerberos */
677c478bd9Sstevel@tonic-gate extern void
687c478bd9Sstevel@tonic-gate gsscred_set_options();
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate extern OM_uint32
717c478bd9Sstevel@tonic-gate gsscred_name_to_unix_cred_ext();
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate extern int
747c478bd9Sstevel@tonic-gate safechown(const char *src, uid_t uid, gid_t gid, int mode);
757c478bd9Sstevel@tonic-gate 
76505d05c7Sgtb extern const char *error_message(long);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate krb5_data tgtname = {
807c478bd9Sstevel@tonic-gate 	0,
817c478bd9Sstevel@tonic-gate 	KRB5_TGS_NAME_SIZE,
827c478bd9Sstevel@tonic-gate 	KRB5_TGS_NAME
837c478bd9Sstevel@tonic-gate };
847c478bd9Sstevel@tonic-gate 
85159d09a2SMark Phalan /* Solaris Kerberos */
867c478bd9Sstevel@tonic-gate static krb5_error_code
krb5_move_ccache(krb5_context kcontext,krb5_principal client,struct passwd * pwd)877c478bd9Sstevel@tonic-gate krb5_move_ccache(krb5_context kcontext, krb5_principal client,
887c478bd9Sstevel@tonic-gate 		struct passwd *pwd)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	char *name = 0;
917c478bd9Sstevel@tonic-gate 	static char ccache_name_buf[CACHE_FILENAME_LEN];
927c478bd9Sstevel@tonic-gate 	krb5_ccache ccache = NULL;
937c478bd9Sstevel@tonic-gate 	krb5_error_code retval;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	name = getenv(KRB5_ENV_CCNAME);
967c478bd9Sstevel@tonic-gate 	if (name == 0)
977c478bd9Sstevel@tonic-gate 		/*
987c478bd9Sstevel@tonic-gate 		 * This means that there was no forwarding
997c478bd9Sstevel@tonic-gate 		 * of creds
1007c478bd9Sstevel@tonic-gate 		 */
1017c478bd9Sstevel@tonic-gate 		return (0);
1027c478bd9Sstevel@tonic-gate 	else {
1037c478bd9Sstevel@tonic-gate 		/*
1047c478bd9Sstevel@tonic-gate 		 * creds have been forwarded and stored in
1057c478bd9Sstevel@tonic-gate 		 * KRB5_ENV_CCNAME and now we need to store it
1067c478bd9Sstevel@tonic-gate 		 * under uid
1077c478bd9Sstevel@tonic-gate 		 */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 		krb5_creds mcreds, save_v5creds;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 		memset(&mcreds, 0, sizeof (mcreds));
1127c478bd9Sstevel@tonic-gate 		memset(&save_v5creds, 0, sizeof (save_v5creds));
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 		mcreds.client =  client;
1157c478bd9Sstevel@tonic-gate 		retval = krb5_build_principal_ext(kcontext, &mcreds.server,
1167c478bd9Sstevel@tonic-gate 				krb5_princ_realm(kcontext,  client)->length,
1177c478bd9Sstevel@tonic-gate 				krb5_princ_realm(kcontext,  client)->data,
1187c478bd9Sstevel@tonic-gate 				tgtname.length, tgtname.data,
1197c478bd9Sstevel@tonic-gate 				krb5_princ_realm(kcontext,  client)->length,
1207c478bd9Sstevel@tonic-gate 				krb5_princ_realm(kcontext,  client)->data,
1217c478bd9Sstevel@tonic-gate 				0);
1227c478bd9Sstevel@tonic-gate 		if (retval) {
1237c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1247c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while creating"
1257c478bd9Sstevel@tonic-gate 					"V5 krbtgt principal "),
1267c478bd9Sstevel@tonic-gate 				error_message(retval));
1277c478bd9Sstevel@tonic-gate 			return (retval);
1287c478bd9Sstevel@tonic-gate 		}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 		mcreds.ticket_flags = 0;
1317c478bd9Sstevel@tonic-gate 		retval = krb5_cc_default(kcontext, &ccache);
1327c478bd9Sstevel@tonic-gate 		if (retval) {
1337c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1347c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while getting "
1357c478bd9Sstevel@tonic-gate 					"default cache "),
1367c478bd9Sstevel@tonic-gate 				error_message(retval));
1377c478bd9Sstevel@tonic-gate 			return (retval);
1387c478bd9Sstevel@tonic-gate 		}
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 		retval = krb5_cc_retrieve_cred(kcontext, ccache,
1417c478bd9Sstevel@tonic-gate 						0,
1427c478bd9Sstevel@tonic-gate 						&mcreds, &save_v5creds);
1437c478bd9Sstevel@tonic-gate 		if (retval) {
1447c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1457c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while retrieving "
1467c478bd9Sstevel@tonic-gate 					"cerdentials "),
1477c478bd9Sstevel@tonic-gate 				error_message(retval));
1487c478bd9Sstevel@tonic-gate 			return (retval);
1497c478bd9Sstevel@tonic-gate 		}
1507c478bd9Sstevel@tonic-gate 		/*
1517c478bd9Sstevel@tonic-gate 		 * reset the env variable and recreate the
1527c478bd9Sstevel@tonic-gate 		 * cache using the default cache name
1537c478bd9Sstevel@tonic-gate 		 */
1547c478bd9Sstevel@tonic-gate 		retval = krb5_cc_destroy(kcontext, ccache);
1557c478bd9Sstevel@tonic-gate 		if (retval) {
1567c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1577c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while destroying cache "),
1587c478bd9Sstevel@tonic-gate 				error_message(retval));
1597c478bd9Sstevel@tonic-gate 			return (retval);
1607c478bd9Sstevel@tonic-gate 		}
1617c478bd9Sstevel@tonic-gate 		krb5_unsetenv(KRB5_ENV_CCNAME);
1627c478bd9Sstevel@tonic-gate 		snprintf(ccache_name_buf,
1637c478bd9Sstevel@tonic-gate 			CACHE_FILENAME_LEN,
1647c478bd9Sstevel@tonic-gate 			"FILE:/tmp/krb5cc_%d", pwd->pw_uid);
1657c478bd9Sstevel@tonic-gate 		krb5_setenv(KRB5_ENV_CCNAME, ccache_name_buf, 1);
1667c478bd9Sstevel@tonic-gate 		retval =  krb5_cc_resolve(kcontext, ccache_name_buf, &ccache);
1677c478bd9Sstevel@tonic-gate 		if (retval) {
1687c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1697c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while resolving cache "),
1707c478bd9Sstevel@tonic-gate 				error_message(retval));
1717c478bd9Sstevel@tonic-gate 			return (retval);
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate 		retval = krb5_cc_initialize(kcontext, ccache, client);
1747c478bd9Sstevel@tonic-gate 		if (retval) {
1757c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1767c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while initializing cache "),
1777c478bd9Sstevel@tonic-gate 				error_message(retval));
1787c478bd9Sstevel@tonic-gate 			return (retval);
1797c478bd9Sstevel@tonic-gate 		}
1807c478bd9Sstevel@tonic-gate 		retval =  krb5_cc_store_cred(kcontext, ccache, &save_v5creds);
1817c478bd9Sstevel@tonic-gate 		if (retval) {
1827c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1837c478bd9Sstevel@tonic-gate 				gettext("KRB5: %s while storing creds "),
1847c478bd9Sstevel@tonic-gate 				error_message(retval));
1857c478bd9Sstevel@tonic-gate 			return (retval);
1867c478bd9Sstevel@tonic-gate 		}
1877c478bd9Sstevel@tonic-gate 		snprintf(ccache_name_buf,
1887c478bd9Sstevel@tonic-gate 			CACHE_FILENAME_LEN,
1897c478bd9Sstevel@tonic-gate 			"/tmp/krb5cc_%d", pwd->pw_uid);
1907c478bd9Sstevel@tonic-gate 		if (safechown(ccache_name_buf, pwd->pw_uid,
1917c478bd9Sstevel@tonic-gate 			pwd->pw_gid, -1) == -1) {
1927c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
1937c478bd9Sstevel@tonic-gate 				gettext("KRB5: Can not change "
1947c478bd9Sstevel@tonic-gate 					"ownership of cache file, "
1957c478bd9Sstevel@tonic-gate 					"possible security breach\n"));
1967c478bd9Sstevel@tonic-gate 		}
1977c478bd9Sstevel@tonic-gate 	}
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	return (0);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
204159d09a2SMark Phalan  * Solaris Kerberos:
2057c478bd9Sstevel@tonic-gate  * krb5_gsscred: Given a kerberos principal try to find the corresponding
2067c478bd9Sstevel@tonic-gate  * local uid via the gss cred table. Return TRUE if the uid was found in the
2077c478bd9Sstevel@tonic-gate  * cred table, otherwise return FALSE.
2087c478bd9Sstevel@tonic-gate  */
2097c478bd9Sstevel@tonic-gate static krb5_boolean
krb5_gsscred(krb5_principal principal,uid_t * uid)2107c478bd9Sstevel@tonic-gate krb5_gsscred(krb5_principal principal, uid_t *uid)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate 	OM_uint32 minor, major;
2137c478bd9Sstevel@tonic-gate 	gss_name_t name;
2147c478bd9Sstevel@tonic-gate 	gss_buffer_desc name_buf;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	name_buf.value = &principal;
2177c478bd9Sstevel@tonic-gate 	name_buf.length = sizeof (principal);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	/*
2207c478bd9Sstevel@tonic-gate 	 * Convert the kerb principal in to a gss name
2217c478bd9Sstevel@tonic-gate 	 */
2227c478bd9Sstevel@tonic-gate 	major = gss_import_name(&minor, &name_buf,
2237c478bd9Sstevel@tonic-gate 				(gss_OID)gss_nt_krb5_principal, &name);
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	if (major != GSS_S_COMPLETE)
2267c478bd9Sstevel@tonic-gate 		return (FALSE);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	gsscred_set_options();
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/*
2317c478bd9Sstevel@tonic-gate 	 * Get the uid mapping from the gsscred table.
2327c478bd9Sstevel@tonic-gate 	 * (but set flag to not call back into this mech as we do krb5
2337c478bd9Sstevel@tonic-gate 	 * auth_to_local name mapping from this module).
2347c478bd9Sstevel@tonic-gate 	 */
2357c478bd9Sstevel@tonic-gate 	major = gsscred_name_to_unix_cred_ext(name, (gss_OID)gss_mech_krb5,
2367c478bd9Sstevel@tonic-gate 					  uid, 0, 0, 0, 0);
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	(void) gss_release_name(&minor, &name);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	if (major != GSS_S_COMPLETE)
2417c478bd9Sstevel@tonic-gate 		return (FALSE);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	return (TRUE);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate  * Given a Kerberos principal "principal", and a local username "luser",
2487c478bd9Sstevel@tonic-gate  * determine whether user is authorized to login according to the
2497c478bd9Sstevel@tonic-gate  * authorization file ("~luser/.k5login" by default).  Returns TRUE
2507c478bd9Sstevel@tonic-gate  * if authorized, FALSE if not authorized.
2517c478bd9Sstevel@tonic-gate  *
2527c478bd9Sstevel@tonic-gate  * If there is no account for "luser" on the local machine, returns
2537c478bd9Sstevel@tonic-gate  * FALSE.  If there is no authorization file, and the given Kerberos
2547c478bd9Sstevel@tonic-gate  * name "server" translates to the same name as "luser" (using
2557c478bd9Sstevel@tonic-gate  * krb5_aname_to_lname()), returns TRUE.  Otherwise, if the authorization file
2567c478bd9Sstevel@tonic-gate  * can't be accessed, returns FALSE.  Otherwise, the file is read for
2577c478bd9Sstevel@tonic-gate  * a matching principal name, instance, and realm.  If one is found,
2587c478bd9Sstevel@tonic-gate  * returns TRUE, if none is found, returns FALSE.
2597c478bd9Sstevel@tonic-gate  *
2607c478bd9Sstevel@tonic-gate  * The file entries are in the format produced by krb5_unparse_name(),
2617c478bd9Sstevel@tonic-gate  * one entry per line.
2627c478bd9Sstevel@tonic-gate  *
2637c478bd9Sstevel@tonic-gate  */
2647c478bd9Sstevel@tonic-gate 
265505d05c7Sgtb krb5_boolean KRB5_CALLCONV
krb5_kuserok(krb5_context context,krb5_principal principal,const char * luser)266505d05c7Sgtb krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate     struct stat sbuf;
2697c478bd9Sstevel@tonic-gate     struct passwd *pwd;
2707c478bd9Sstevel@tonic-gate     char pbuf[MAXPATHLEN];
2717c478bd9Sstevel@tonic-gate     krb5_boolean isok = FALSE;
2727c478bd9Sstevel@tonic-gate     FILE *fp;
2737c478bd9Sstevel@tonic-gate     char kuser[MAX_USERNAME];
2747c478bd9Sstevel@tonic-gate     char *princname;
2757c478bd9Sstevel@tonic-gate     char linebuf[BUFSIZ];
2767c478bd9Sstevel@tonic-gate     char *newline;
277159d09a2SMark Phalan     /* Solaris Kerberos */
2787c478bd9Sstevel@tonic-gate     uid_t uid;
2797c478bd9Sstevel@tonic-gate     int gobble;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate     /* no account => no access */
282505d05c7Sgtb     char pwbuf[BUFSIZ];
283505d05c7Sgtb     struct passwd pwx;
284159d09a2SMark Phalan     if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
2857c478bd9Sstevel@tonic-gate 	return(FALSE);
2867c478bd9Sstevel@tonic-gate     (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
2877c478bd9Sstevel@tonic-gate     pbuf[sizeof(pbuf) - 1] = '\0';
2887c478bd9Sstevel@tonic-gate     (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate     if (access(pbuf, F_OK)) {	 /* not accessible */
2917c478bd9Sstevel@tonic-gate 	/*
292*48bbca81SDaniel Hoffman 	 * if they're trying to log in as themself, and there is no .k5login file,
293*48bbca81SDaniel Hoffman 	 * let them.  First, have krb5 check it's rules.  If no success,
2947c478bd9Sstevel@tonic-gate 	 * search the gsscred table (the sequence here should be consistent
2957c478bd9Sstevel@tonic-gate 	 * with the uid mappings done for gssd).
2967c478bd9Sstevel@tonic-gate 	 */
2977c478bd9Sstevel@tonic-gate 	if (!(krb5_aname_to_localname(context, principal,
2987c478bd9Sstevel@tonic-gate 				      sizeof(kuser), kuser))
2997c478bd9Sstevel@tonic-gate 	    && (strcmp(kuser, luser) == 0)) {
300159d09a2SMark Phalan 		/* Solaris Kerberos */
3017c478bd9Sstevel@tonic-gate 		if (krb5_move_ccache(context, principal, pwd))
3027c478bd9Sstevel@tonic-gate 			return (FALSE);
3037c478bd9Sstevel@tonic-gate 	    	return(TRUE);
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	if (krb5_gsscred(principal, &uid)) {
3077c478bd9Sstevel@tonic-gate #ifdef DEBUG
3087c478bd9Sstevel@tonic-gate 	    char *princname;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	    (void)krb5_unparse_name(context, principal, &princname);
3117c478bd9Sstevel@tonic-gate 	    syslog(LOG_DEBUG, "gsscred mapped %s to %d expecting %d (%s)\n",
3127c478bd9Sstevel@tonic-gate 		   princname, uid, pwd->pw_uid, luser);
3137c478bd9Sstevel@tonic-gate 	    free(princname);
3147c478bd9Sstevel@tonic-gate #endif
3157c478bd9Sstevel@tonic-gate 	    if (uid == pwd->pw_uid) {
3167c478bd9Sstevel@tonic-gate 		if (krb5_move_ccache(context, principal, pwd))
3177c478bd9Sstevel@tonic-gate 			return (FALSE);
3187c478bd9Sstevel@tonic-gate 		return (TRUE);
319004388ebScasper 	    }
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate     }
3237c478bd9Sstevel@tonic-gate     if (krb5_unparse_name(context, principal, &princname))
3247c478bd9Sstevel@tonic-gate 	return(FALSE);			/* no hope of matching */
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate     /* open ~/.k5login */
327159d09a2SMark Phalan     /* Solaris Kerberos */
328004388ebScasper     if ((fp = fopen(pbuf, "rF")) == NULL) {
3297c478bd9Sstevel@tonic-gate 	free(princname);
3307c478bd9Sstevel@tonic-gate 	return(FALSE);
3317c478bd9Sstevel@tonic-gate     }
3327c478bd9Sstevel@tonic-gate     /*
3337c478bd9Sstevel@tonic-gate      * For security reasons, the .k5login file must be owned either by
3347c478bd9Sstevel@tonic-gate      * the user himself, or by root.  Otherwise, don't grant access.
3357c478bd9Sstevel@tonic-gate      */
3367c478bd9Sstevel@tonic-gate     if (fstat(fileno(fp), &sbuf)) {
3377c478bd9Sstevel@tonic-gate 	fclose(fp);
3387c478bd9Sstevel@tonic-gate 	free(princname);
3397c478bd9Sstevel@tonic-gate 	return(FALSE);
3407c478bd9Sstevel@tonic-gate     }
341159d09a2SMark Phalan     if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) {
3427c478bd9Sstevel@tonic-gate 	fclose(fp);
3437c478bd9Sstevel@tonic-gate 	free(princname);
3447c478bd9Sstevel@tonic-gate 	return(FALSE);
3457c478bd9Sstevel@tonic-gate     }
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate     /* check each line */
3487c478bd9Sstevel@tonic-gate     while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
3497c478bd9Sstevel@tonic-gate 	/* null-terminate the input string */
3507c478bd9Sstevel@tonic-gate 	linebuf[BUFSIZ-1] = '\0';
3517c478bd9Sstevel@tonic-gate 	newline = NULL;
3527c478bd9Sstevel@tonic-gate 	/* nuke the newline if it exists */
3537c478bd9Sstevel@tonic-gate 	if ((newline = strchr(linebuf, '\n')))
3547c478bd9Sstevel@tonic-gate 	    *newline = '\0';
3557c478bd9Sstevel@tonic-gate 	if (!strcmp(linebuf, princname)) {
3567c478bd9Sstevel@tonic-gate 	    isok = TRUE;
357159d09a2SMark Phalan 	    /* Solaris Kerberos */
3587c478bd9Sstevel@tonic-gate 	    if (krb5_move_ccache(context, principal, pwd))
3597c478bd9Sstevel@tonic-gate 		return (FALSE);
3607c478bd9Sstevel@tonic-gate 	    continue;
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate 	/* clean up the rest of the line if necessary */
3637c478bd9Sstevel@tonic-gate 	if (!newline)
3647c478bd9Sstevel@tonic-gate 	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
3657c478bd9Sstevel@tonic-gate     }
3667c478bd9Sstevel@tonic-gate     free(princname);
3677c478bd9Sstevel@tonic-gate     fclose(fp);
3687c478bd9Sstevel@tonic-gate     return(isok);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
371159d09a2SMark Phalan /* Solaris Kerberos */
3727c478bd9Sstevel@tonic-gate OM_uint32
krb5_gss_userok(OM_uint32 * minor,const gss_name_t pname,const char * user,int * user_ok)373ab9b2e15Sgtb krb5_gss_userok(OM_uint32 *minor,
3747c478bd9Sstevel@tonic-gate 		const gss_name_t pname,
3757c478bd9Sstevel@tonic-gate 		const char *user,
3767c478bd9Sstevel@tonic-gate 		int *user_ok)
3777c478bd9Sstevel@tonic-gate {
378ab9b2e15Sgtb 	krb5_context ctxt;
379ab9b2e15Sgtb 	OM_uint32 kret;
380ab9b2e15Sgtb 
3817c478bd9Sstevel@tonic-gate 	if (pname == NULL || user == NULL)
3827c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_READ);
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	if (minor == NULL || user_ok == NULL)
3857c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
386004388ebScasper 
3877c478bd9Sstevel@tonic-gate 	*user_ok = 0;
3887c478bd9Sstevel@tonic-gate 
389*48bbca81SDaniel Hoffman 	kret = krb5_gss_init_context(&ctxt);
390*48bbca81SDaniel Hoffman 	if (kret) {
391*48bbca81SDaniel Hoffman 		*minor = kret;
392*48bbca81SDaniel Hoffman 		return (GSS_S_FAILURE);
393ab9b2e15Sgtb 	}
394ab9b2e15Sgtb 
3957c478bd9Sstevel@tonic-gate 	if (! kg_validate_name(pname)) {
396ab9b2e15Sgtb 		*minor = (OM_uint32) G_VALIDATE_FAILED;
397ab9b2e15Sgtb 		krb5_free_context(ctxt);
398ab9b2e15Sgtb 		return (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if (krb5_kuserok(ctxt, (krb5_principal) pname, user)) {
4027c478bd9Sstevel@tonic-gate 		*user_ok = 1;
4037c478bd9Sstevel@tonic-gate 	}
404ab9b2e15Sgtb 
405ab9b2e15Sgtb 	krb5_free_context(ctxt);
4067c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
4077c478bd9Sstevel@tonic-gate }
408159d09a2SMark Phalan 
409159d09a2SMark Phalan #else /* _WIN32 */
410159d09a2SMark Phalan 
411159d09a2SMark Phalan /*
412159d09a2SMark Phalan  * If the given Kerberos name "server" translates to the same name as "luser"
413159d09a2SMark Phalan  * (using * krb5_aname_to_lname()), returns TRUE.
414159d09a2SMark Phalan  */
415159d09a2SMark Phalan krb5_boolean KRB5_CALLCONV
krb5_kuserok(context,principal,luser)416159d09a2SMark Phalan krb5_kuserok(context, principal, luser)
417159d09a2SMark Phalan     krb5_context context;
418159d09a2SMark Phalan     krb5_principal principal;
419159d09a2SMark Phalan     const char *luser;
420159d09a2SMark Phalan {
421159d09a2SMark Phalan     char kuser[50];
422159d09a2SMark Phalan 
423159d09a2SMark Phalan     if (krb5_aname_to_localname(context, principal, sizeof(kuser), kuser))
424159d09a2SMark Phalan         return FALSE;
425159d09a2SMark Phalan 
426159d09a2SMark Phalan     if (strcmp(kuser, luser) == 0)
427159d09a2SMark Phalan 	    return TRUE;
428159d09a2SMark Phalan 
429159d09a2SMark Phalan     return FALSE;
430159d09a2SMark Phalan }
431159d09a2SMark Phalan #endif /* _WIN32 */
432