/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Routines to set gssd value of uid and replace getuid libsys call. */ #include #include #include #include #include #include #include #include static uid_t krb5_cc_uid; #define LOWPRIVS "basic,!file_link_any,!proc_info,!proc_session," \ "!proc_fork,!proc_exec" static priv_set_t *lowprivs = NULL; static priv_set_t *highprivs = NULL; /* * NOTE WELL: This assumes gssd is NOT multi-threaded. Do NOT add -A to * the rpcgen argument list in the Makefile unless you also remove this * assumption. */ void set_gssd_uid(uid_t uid) { /* Initialize */ if (lowprivs == NULL) { /* L, P & I shall not change in gssd; we manipulate P though */ if ((highprivs = priv_allocset()) == NULL || (lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) { printf(gettext( "fatal: can't allocate privilege set (%s)\n"), strerror(ENOMEM)); syslog(LOG_ERR, "Fatal: can't allocate privilege " "set (%s)"), strerror(ENOMEM); exit(1); } /* P has the privs we need when we need privs */ (void) getppriv(PRIV_PERMITTED, highprivs); /* * In case "basic" grows privs not excluded in LOWPRIVS * but excluded in the service's method_context */ priv_intersect(highprivs, lowprivs); (void) setpflags(PRIV_AWARE, 1); } printf(gettext("set_gssd_uid called with uid = %d\n"), uid); /* * nfsd runs as UID 1, so upcalls triggered by nfsd will cause uid to * 1 here, but nfsd's upcalls need to run as root with privs here. */ if (uid == 1) uid = 0; /* * Set the value of krb5_cc_uid, so it can be retrieved when * app_krb5_user_uid() is called by the underlying mechanism * libraries. This should go away soon. */ krb5_cc_uid = uid; /* Claw privs back */ (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, highprivs); /* * Switch uid and set the saved set-uid to 0 so setuid(0) will work * later. */ if (setuid(0) != 0 || (uid != 0 && setreuid(uid, -1) != 0) || (uid != 0 && seteuid(uid) != 0)) { /* Not enough privs, so bail! */ printf(gettext( "fatal: gssd is running with insufficient privilege\n")); syslog(LOG_ERR, "Fatal: gssd is running with insufficient " "privilege."); exit(1); } /* Temporarily drop privs, but only if uid != 0 */ if (uid != 0) (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, lowprivs); } uid_t app_krb5_user_uid(void) { /* * return the value set when one of the gssd procedures was * entered. This is the value of the uid under which the * underlying mechanism library must operate in order to * get the user's credentials. This call is necessary since * gssd runs as root and credentials are many times stored * in files and directories specific to the user */ printf(gettext( "getuid called and returning krb5_cc_uid = %d\n"), krb5_cc_uid); return (krb5_cc_uid); }