# for kdc
AC_CHECK_HEADERS(sys/sockio.h ifaddrs.h unistd.h fnmatch.h)
-AC_CHECK_FUNCS(vsprintf vasprintf vsnprintf strlcpy fnmatch)
+AC_CHECK_FUNCS(vsprintf vasprintf vsnprintf strlcpy fnmatch secure_getenv)
EXTRA_SUPPORT_SYMS=
AC_CHECK_FUNC(strlcpy,
#include <stdlib.h>
],swab,1)
+AC_CHECK_FUNC(secure_getenv,
+[SECURE_GETENV_ST_OBJ=
+SECURE_GETENV_OBJ=
+SECURE_GETENV_INIT=],
+[SECURE_GETENV_ST_OBJ=secure_getenv.o
+SECURE_GETENV_OBJ='$(OUTPRE)secure_getenv.$(OBJEXT)'
+SECURE_GETENV_INIT=k5_secure_getenv_init
+EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_secure_getenv"])
+AC_SUBST(SECURE_GETENV_OBJ)
+AC_SUBST(SECURE_GETENV_ST_OBJ)
+AC_SUBST(SECURE_GETENV_INIT)
+
AC_PROG_AWK
KRB5_AC_INET6
KRB5_SOCKADDR_SA_LEN
AC_C_CONST
AC_HEADER_DIRENT
AC_FUNC_STRERROR_R
-AC_CHECK_FUNCS(strdup setvbuf seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror timegm explicit_bzero explicit_memset)
+AC_CHECK_FUNCS(strdup setvbuf seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror timegm explicit_bzero explicit_memset getresuid getresgid)
AC_CHECK_FUNC(mkstemp,
[MKSTEMP_ST_OBJ=
LIBMAJOR=@SUPPORTLIB_MAJOR@
LIBMINOR=1
-LIBINITFUNC=krb5int_thread_support_init
+LIBINITFUNC=krb5int_thread_support_init @SECURE_GETENV_INIT@
LIBFINIFUNC=krb5int_thread_support_fini
GETTIMEOFDAY_ST_OBJ= @GETTIMEOFDAY_ST_OBJ@
##DOS##GETOPT_LONG_ST_OBJ= getopt_long.o
##DOS##GETOPT_LONG_OBJ= $(OUTPRE)getopt_long.$(OBJEXT)
+SECURE_GETENV_ST_OBJ= @SECURE_GETENV_ST_OBJ@
+SECURE_GETENV_OBJ= @SECURE_GETENV_OBJ@
+##DOS##SECURE_GETENV_ST_OBJ=
+##DOS##SECURE_GETENV_OBJ=
+
IPC_ST_OBJ=
IPC_OBJ=
##DOS##IPC_ST_OBJ= ipc_stream.o
$(PRINTF_ST_OBJ) \
$(MKSTEMP_ST_OBJ) \
$(GETOPT_ST_OBJ) \
- $(GETOPT_LONG_ST_OBJ)
+ $(GETOPT_LONG_ST_OBJ) \
+ $(SECURE_GETENV_OBJ)
LIBOBJS= \
$(OUTPRE)threads.$(OBJEXT) \
$(PRINTF_OBJ) \
$(MKSTEMP_OBJ) \
$(GETOPT_OBJ) \
- $(GETOPT_LONG_OBJ)
+ $(GETOPT_LONG_OBJ) \
+ $(SECURE_GETENV_OBJ)
SRCS=\
$(srcdir)/threads.c \
$(srcdir)/t_utf8.c \
$(srcdir)/t_utf16.c \
$(srcdir)/getopt.c \
- $(srcdir)/getopt_long.c
+ $(srcdir)/getopt_long.c \
+ $(srcdir)/secure_getenv.c
SHLIB_EXPDEPS =
# Add -lm if dumping thread stats, for sqrt.
--- /dev/null
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* util/support/secure_getenv.c - secure_getenv() portability support */
+/*
+ * Copyright (C) 2019 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains the fallback implementation for secure_getenv(), which is
+ * currently only provided by glibc 2.17 and later. The goal is to ignore the
+ * environment if this process is (or previously was) running at elevated
+ * privilege compared to the calling process.
+ *
+ * In this fallback version we compare the real and effective uid/gid, and also
+ * compare the saved uid/gid if possible. These comparisons detect a setuid or
+ * setgid process which is still running with elevated privilege; if we can
+ * fetch the saved uid/gid, we also detect a process which has temporarily
+ * dropped privilege with seteuid() or setegid(). These comparisons do not
+ * detect the case where a setuid or setgid process has permanently dropped
+ * privilege before the library initializer ran; this is not ideal because such
+ * a process may possess a privileged resource or have privileged information
+ * in its address space.
+ *
+ * Heimdal also looks at the ELF aux vector in /proc/self/auxv to determine the
+ * starting uid/euid/gid/euid on Solaris/Illumos and NetBSD. On FreeBSD this
+ * approach can determine the executable path to do a stat() check. We do not
+ * go to this length due to the amount of code required.
+ *
+ * The BSDs and Solaris provide issetugid(), but the FreeBSD and NetBSD
+ * versions are not useful; they return true if a non-setuid/setgid executable
+ * is run by root and drops privilege, such as Apache httpd. We do not want to
+ * ignore the process environment in this case.
+ *
+ * On some platforms a process may have elevated privilege via mechanisms other
+ * than setuid/setgid. glibc's secure_getenv() should detect these cases on
+ * Linux; we do not detect them in this fallback version.
+ */
+
+#include "k5-platform.h"
+
+static int elevated_privilege = 0;
+
+MAKE_INIT_FUNCTION(k5_secure_getenv_init);
+
+int
+k5_secure_getenv_init()
+{
+ int saved_errno = errno;
+
+#ifdef HAVE_GETRESUID
+ {
+ uid_t r, e, s;
+ if (getresuid(&r, &e, &s) == 0) {
+ if (r != e || r != s)
+ elevated_privilege = 1;
+ }
+ }
+#else
+ if (getuid() != geteuid())
+ elevated_privilege = 1;
+#endif
+
+#ifdef HAVE_GETRESGID
+ {
+ gid_t r, e, s;
+ if (!elevated_privilege && getresgid(&r, &e, &s) == 0) {
+ if (r != e || r != s)
+ elevated_privilege = 1;
+ }
+ }
+#else
+ if (!elevated_privilege && getgid() != getegid())
+ elevated_privilege = 1;
+#endif
+
+ errno = saved_errno;
+ return 0;
+}
+
+char *
+k5_secure_getenv(const char *name)
+{
+ if (CALL_INIT_FUNCTION(k5_secure_getenv_init) != 0)
+ return NULL;
+ return elevated_privilege ? NULL : getenv(name);
+}