1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Routines to set gssd value of uid and replace getuid libsys call. 28 */ 29 30 #include <sys/types.h> 31 #include <unistd.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <libintl.h> 35 #include <priv.h> 36 #include <errno.h> 37 #include <syslog.h> 38 39 static uid_t krb5_cc_uid; 40 #define LOWPRIVS "basic,!file_link_any,!proc_info,!proc_session," \ 41 "!proc_fork,!proc_exec" 42 43 static priv_set_t *lowprivs = NULL; 44 static priv_set_t *highprivs = NULL; 45 46 /* 47 * NOTE WELL: This assumes gssd is NOT multi-threaded. Do NOT add -A to 48 * the rpcgen argument list in the Makefile unless you also remove this 49 * assumption. 50 */ 51 52 void 53 set_gssd_uid(uid_t uid) 54 { 55 /* Initialize */ 56 if (lowprivs == NULL) { 57 /* L, P & I shall not change in gssd; we manipulate P though */ 58 if ((highprivs = priv_allocset()) == NULL || 59 (lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) { 60 printf(gettext( 61 "fatal: can't allocate privilege set (%s)\n"), 62 strerror(ENOMEM)); 63 syslog(LOG_ERR, "Fatal: can't allocate privilege " 64 "set (%s)"), strerror(ENOMEM); 65 exit(1); 66 } 67 /* P has the privs we need when we need privs */ 68 (void) getppriv(PRIV_PERMITTED, highprivs); 69 70 /* 71 * In case "basic" grows privs not excluded in LOWPRIVS 72 * but excluded in the service's method_context 73 */ 74 priv_intersect(highprivs, lowprivs); 75 76 (void) setpflags(PRIV_AWARE, 1); 77 } 78 79 printf(gettext("set_gssd_uid called with uid = %d\n"), uid); 80 81 /* 82 * nfsd runs as UID 1, so upcalls triggered by nfsd will cause uid to 83 * 1 here, but nfsd's upcalls need to run as root with privs here. 84 */ 85 if (uid == 1) 86 uid = 0; 87 88 /* 89 * Set the value of krb5_cc_uid, so it can be retrieved when 90 * app_krb5_user_uid() is called by the underlying mechanism 91 * libraries. This should go away soon. 92 */ 93 krb5_cc_uid = uid; 94 95 /* Claw privs back */ 96 (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, highprivs); 97 98 /* 99 * Switch uid and set the saved set-uid to 0 so setuid(0) will work 100 * later. 101 */ 102 if (setuid(0) != 0 || 103 (uid != 0 && setreuid(uid, -1) != 0) || 104 (uid != 0 && seteuid(uid) != 0)) { 105 106 /* Not enough privs, so bail! */ 107 printf(gettext( 108 "fatal: gssd is running with insufficient privilege\n")); 109 syslog(LOG_ERR, "Fatal: gssd is running with insufficient " 110 "privilege."); 111 exit(1); 112 } 113 114 /* Temporarily drop privs, but only if uid != 0 */ 115 if (uid != 0) 116 (void) setppriv(PRIV_SET, PRIV_EFFECTIVE, lowprivs); 117 } 118 119 uid_t 120 app_krb5_user_uid(void) 121 { 122 /* 123 * return the value set when one of the gssd procedures was 124 * entered. This is the value of the uid under which the 125 * underlying mechanism library must operate in order to 126 * get the user's credentials. This call is necessary since 127 * gssd runs as root and credentials are many times stored 128 * in files and directories specific to the user 129 */ 130 printf(gettext( 131 "getuid called and returning krb5_cc_uid = %d\n"), krb5_cc_uid); 132 return (krb5_cc_uid); 133 } 134