10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54271Srie * Common Development and Distribution License (the "License"). 64271Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*9763SPeter.Shoults@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 234271Srie * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * Routines to set gssd value of uid and replace getuid libsys call. 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <sys/types.h> 310Sstevel@tonic-gate #include <unistd.h> 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #include <stdlib.h> 340Sstevel@tonic-gate #include <libintl.h> 35*9763SPeter.Shoults@Sun.COM #include <priv.h> 36*9763SPeter.Shoults@Sun.COM #include <errno.h> 37*9763SPeter.Shoults@Sun.COM #include <syslog.h> 380Sstevel@tonic-gate 394271Srie static uid_t krb5_cc_uid; 40*9763SPeter.Shoults@Sun.COM #define LOWPRIVS "basic,!file_link_any,!proc_info,!proc_session," \ 41*9763SPeter.Shoults@Sun.COM "!proc_fork,!proc_exec" 42*9763SPeter.Shoults@Sun.COM 43*9763SPeter.Shoults@Sun.COM static priv_set_t *lowprivs = NULL; 44*9763SPeter.Shoults@Sun.COM static priv_set_t *highprivs = NULL; 45*9763SPeter.Shoults@Sun.COM 46*9763SPeter.Shoults@Sun.COM /* 47*9763SPeter.Shoults@Sun.COM * NOTE WELL: This assumes gssd is NOT multi-threaded. Do NOT add -A to 48*9763SPeter.Shoults@Sun.COM * the rpcgen argument list in the Makefile unless you also remove this 49*9763SPeter.Shoults@Sun.COM * assumption. 50*9763SPeter.Shoults@Sun.COM */ 510Sstevel@tonic-gate 520Sstevel@tonic-gate void 534271Srie set_gssd_uid(uid_t uid) 540Sstevel@tonic-gate { 55*9763SPeter.Shoults@Sun.COM /* Initialize */ 56*9763SPeter.Shoults@Sun.COM if (lowprivs == NULL) { 57*9763SPeter.Shoults@Sun.COM /* L, P & I shall not change in gssd; we manipulate P though */ 58*9763SPeter.Shoults@Sun.COM if ((highprivs = priv_allocset()) == NULL || 59*9763SPeter.Shoults@Sun.COM (lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) { 60*9763SPeter.Shoults@Sun.COM printf(gettext( 61*9763SPeter.Shoults@Sun.COM "fatal: can't allocate privilege set (%s)\n"), 62*9763SPeter.Shoults@Sun.COM strerror(ENOMEM)); 63*9763SPeter.Shoults@Sun.COM syslog(LOG_ERR, "Fatal: can't allocate privilege " 64*9763SPeter.Shoults@Sun.COM "set (%s)"), strerror(ENOMEM); 65*9763SPeter.Shoults@Sun.COM exit(1); 66*9763SPeter.Shoults@Sun.COM } 67*9763SPeter.Shoults@Sun.COM /* P has the privs we need when we need privs */ 68*9763SPeter.Shoults@Sun.COM (void) getppriv(PRIV_PERMITTED, highprivs); 69*9763SPeter.Shoults@Sun.COM 70*9763SPeter.Shoults@Sun.COM /* 71*9763SPeter.Shoults@Sun.COM * In case "basic" grows privs not excluded in LOWPRIVS 72*9763SPeter.Shoults@Sun.COM * but excluded in the service's method_context 73*9763SPeter.Shoults@Sun.COM */ 74*9763SPeter.Shoults@Sun.COM priv_intersect(highprivs, lowprivs); 75*9763SPeter.Shoults@Sun.COM 76*9763SPeter.Shoults@Sun.COM (void) setpflags(PRIV_AWARE, 1); 77*9763SPeter.Shoults@Sun.COM } 78*9763SPeter.Shoults@Sun.COM 79*9763SPeter.Shoults@Sun.COM printf(gettext("set_gssd_uid called with uid = %d\n"), uid); 80*9763SPeter.Shoults@Sun.COM 810Sstevel@tonic-gate /* 82*9763SPeter.Shoults@Sun.COM * nfsd runs as UID 1, so upcalls triggered by nfsd will cause uid to 83*9763SPeter.Shoults@Sun.COM * 1 here, but nfsd's upcalls need to run as root with privs here. 84*9763SPeter.Shoults@Sun.COM */ 85*9763SPeter.Shoults@Sun.COM if (uid == 1) 86*9763SPeter.Shoults@Sun.COM uid = 0; 87*9763SPeter.Shoults@Sun.COM 88*9763SPeter.Shoults@Sun.COM /* 89*9763SPeter.Shoults@Sun.COM * Set the value of krb5_cc_uid, so it can be retrieved when 90*9763SPeter.Shoults@Sun.COM * app_krb5_user_uid() is called by the underlying mechanism 91*9763SPeter.Shoults@Sun.COM * libraries. This should go away soon. 920Sstevel@tonic-gate */ 934271Srie krb5_cc_uid = uid; 94*9763SPeter.Shoults@Sun.COM 95*9763SPeter.Shoults@Sun.COM /* Claw privs back */ 96*9763SPeter.Shoults@Sun.COM (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, highprivs); 97*9763SPeter.Shoults@Sun.COM 98*9763SPeter.Shoults@Sun.COM /* 99*9763SPeter.Shoults@Sun.COM * Switch uid and set the saved set-uid to 0 so setuid(0) will work 100*9763SPeter.Shoults@Sun.COM * later. 101*9763SPeter.Shoults@Sun.COM */ 102*9763SPeter.Shoults@Sun.COM if (setuid(0) != 0 || 103*9763SPeter.Shoults@Sun.COM (uid != 0 && setreuid(uid, -1) != 0) || 104*9763SPeter.Shoults@Sun.COM (uid != 0 && seteuid(uid) != 0)) { 105*9763SPeter.Shoults@Sun.COM 106*9763SPeter.Shoults@Sun.COM /* Not enough privs, so bail! */ 107*9763SPeter.Shoults@Sun.COM printf(gettext( 108*9763SPeter.Shoults@Sun.COM "fatal: gssd is running with insufficient privilege\n")); 109*9763SPeter.Shoults@Sun.COM syslog(LOG_ERR, "Fatal: gssd is running with insufficient " 110*9763SPeter.Shoults@Sun.COM "privilege."); 111*9763SPeter.Shoults@Sun.COM exit(1); 112*9763SPeter.Shoults@Sun.COM } 113*9763SPeter.Shoults@Sun.COM 114*9763SPeter.Shoults@Sun.COM /* Temporarily drop privs, but only if uid != 0 */ 115*9763SPeter.Shoults@Sun.COM if (uid != 0) 116*9763SPeter.Shoults@Sun.COM (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, lowprivs); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate uid_t 1204271Srie app_krb5_user_uid(void) 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate /* 1230Sstevel@tonic-gate * return the value set when one of the gssd procedures was 1240Sstevel@tonic-gate * entered. This is the value of the uid under which the 1250Sstevel@tonic-gate * underlying mechanism library must operate in order to 1260Sstevel@tonic-gate * get the user's credentials. This call is necessary since 1270Sstevel@tonic-gate * gssd runs as root and credentials are many times stored 1280Sstevel@tonic-gate * in files and directories specific to the user 1290Sstevel@tonic-gate */ 1300Sstevel@tonic-gate printf(gettext( 131*9763SPeter.Shoults@Sun.COM "getuid called and returning krb5_cc_uid = %d\n"), krb5_cc_uid); 1324271Srie return (krb5_cc_uid); 1330Sstevel@tonic-gate } 134