summaryrefslogtreecommitdiff
path: root/usr/src/cmd/gss/gssd/gssd_getuid.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/gss/gssd/gssd_getuid.c')
-rw-r--r--usr/src/cmd/gss/gssd/gssd_getuid.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/usr/src/cmd/gss/gssd/gssd_getuid.c b/usr/src/cmd/gss/gssd/gssd_getuid.c
index 874f7d1d52..0835247f72 100644
--- a/usr/src/cmd/gss/gssd/gssd_getuid.c
+++ b/usr/src/cmd/gss/gssd/gssd_getuid.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Routines to set gssd value of uid and replace getuid libsys call.
*/
@@ -34,18 +32,88 @@
#include <stdio.h>
#include <stdlib.h>
#include <libintl.h>
+#include <priv.h>
+#include <errno.h>
+#include <syslog.h>
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);
+
/*
- * set the value of krb5_cc_uid, so it can be retrieved when
- * app_krb5_user_uid() is called by the underlying mechanism libraries.
+ * 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.
*/
- printf(gettext("set_gssd_uid called with uid = %d\n"), uid);
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
@@ -60,6 +128,6 @@ app_krb5_user_uid(void)
* in files and directories specific to the user
*/
printf(gettext(
- "getuid called and returning gsssd_uid = %d\n"), krb5_cc_uid);
+ "getuid called and returning krb5_cc_uid = %d\n"), krb5_cc_uid);
return (krb5_cc_uid);
}