e51dac3
SELinux bases access to files mainly on the domain of the requesting
e51dac3
process and the context applied to the file.
e51dac3
e51dac3
In many cases, applications needn't be SELinux aware to work properly,
e51dac3
because SELinux can apply a default label to a file based on the label
e51dac3
of the directory in which it's created.
e51dac3
e51dac3
In the case of files such as /etc/krb5.keytab, however, this isn't
e51dac3
sufficient, as /etc/krb5.keytab will almost always need given a label
e51dac3
which differs from that of /etc/issue or /etc/resolv.conf.
e51dac3
e51dac3
To give the file the correct label, we can either force a "restorecon"
e51dac3
call to fix a file's label after it's created, or create the file with
e51dac3
the right label, as we do here.  We lean on THREEPARAMOPEN and define a
e51dac3
similar macro named WRITABLEFOPEN with which we replace several uses of
e51dac3
fopen().
e51dac3
e51dac3
diff -ur krb5-1.6.3/src/aclocal.m4 krb5-1.6.3/src/aclocal.m4
e51dac3
--- krb5-1.6.3/src/aclocal.m4	2008-03-06 19:04:59.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/aclocal.m4	2008-03-06 17:31:21.000000000 -0500
e51dac3
@@ -102,6 +102,7 @@
e51dac3
 dnl
e51dac3
 KRB5_AC_PRAGMA_WEAK_REF
e51dac3
 WITH_LDAP
e51dac3
+KRB5_WITH_SELINUX
e51dac3
 KRB5_LIB_PARAMS
e51dac3
 KRB5_AC_INITFINI
e51dac3
 KRB5_AC_ENABLE_THREADS
e51dac3
@@ -1902,3 +1903,50 @@
e51dac3
 AC_SUBST(PAM_MAN)
e51dac3
 AC_SUBST(NON_PAM_MAN)
e51dac3
 ])dnl
e51dac3
+dnl
e51dac3
+dnl Use libselinux to set file contexts on newly-created files.
e51dac3
+dnl 
e51dac3
+AC_DEFUN(KRB5_WITH_SELINUX,[
e51dac3
+AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])],
e51dac3
+           withselinux="$withval",withselinux=auto)
e51dac3
+old_LIBS="$LIBS"
e51dac3
+if test "$withselinux" != no ; then
e51dac3
+       AC_MSG_RESULT([checking for libselinux...])
e51dac3
+       SELINUX_LIBS=
e51dac3
+       AC_CHECK_HEADERS(selinux/selinux.h)
e51dac3
+       if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then
e51dac3
+               if test "$withselinux" = auto ; then
e51dac3
+                       AC_MSG_RESULT([Unable to locate selinux/selinux.h.])
e51dac3
+                       withselinux=no
e51dac3
+               else
e51dac3
+                       AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
e51dac3
+               fi
e51dac3
+       fi
e51dac3
+
e51dac3
+       LIBS=
e51dac3
+       unset ac_cv_func_setfscreatecon
e51dac3
+       AC_CHECK_FUNCS(setfscreatecon)
e51dac3
+       if test "x$ac_cv_func_setfscreatecon" = xno ; then
e51dac3
+               AC_CHECK_LIB(selinux,setfscreatecon)
e51dac3
+               unset ac_cv_func_setfscreatecon
e51dac3
+               AC_CHECK_FUNCS(setfscreatecon)
e51dac3
+               if test "x$ac_cv_func_setfscreatecon" = xyes ; then
e51dac3
+                       SELINUX_LIBS="$LIBS"
e51dac3
+               else
e51dac3
+                       if test "$withselinux" = auto ; then
e51dac3
+                               AC_MSG_RESULT([Unable to locate libselinux.])
e51dac3
+                               withselinux=no
e51dac3
+                       else
e51dac3
+                               AC_MSG_ERROR([Unable to locate libselinux.])
e51dac3
+                       fi
e51dac3
+               fi
e51dac3
+       fi
e51dac3
+       if test "$withselinux" != no ; then
e51dac3
+               AC_MSG_RESULT([Using SELinux.])
e51dac3
+               AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.])
e51dac3
+               SELINUX_LIBS="$LIBS"
e51dac3
+       fi
e51dac3
+fi
e51dac3
+LIBS="$old_LIBS"
e51dac3
+AC_SUBST(SELINUX_LIBS)
e51dac3
+])dnl
e51dac3
diff -ur krb5-1.6.3/src/appl/bsd/configure.in krb5-1.6.3/src/appl/bsd/configure.in
e51dac3
--- krb5-1.6.3/src/appl/bsd/configure.in	2008-03-06 19:04:59.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/appl/bsd/configure.in	2008-03-06 18:05:45.000000000 -0500
e51dac3
@@ -25,6 +25,7 @@
e51dac3
       LOGINLIBS="$LOGINLIBS -lodm -ls -lcfg" 
e51dac3
       )))
e51dac3
 KRB5_WITH_PAM
e51dac3
+KRB5_WITH_SELINUX
e51dac3
 dnl
e51dac3
 dnl Make our operating system-specific security checks and definitions for
e51dac3
 dnl login.
e51dac3
diff -ur krb5-1.6.3/src/appl/gssftp/configure.in krb5-1.6.3/src/appl/gssftp/configure.in
e51dac3
--- krb5-1.6.3/src/appl/gssftp/configure.in	2008-03-06 19:04:59.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/appl/gssftp/configure.in	2008-03-06 18:08:03.000000000 -0500
e51dac3
@@ -18,6 +18,7 @@
e51dac3
 AC_CHECK_FUNCS(getcwd getdtablesize getusershell seteuid setreuid setresuid strerror getenv)
e51dac3
 AC_CHECK_LIB(crypt,crypt) dnl 
e51dac3
 KRB5_WITH_PAM
e51dac3
+KRB5_WITH_SELINUX
e51dac3
 KRB5_AC_LIBUTIL
e51dac3
 dnl 
e51dac3
 dnl copied from appl/bsd/configure.in
e51dac3
diff -ur krb5-1.6.3/src/appl/telnet/configure.in krb5-1.6.3/src/appl/telnet/configure.in
e51dac3
--- krb5-1.6.3/src/appl/telnet/configure.in	2006-03-27 23:35:02.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/appl/telnet/configure.in	2008-03-06 18:08:49.000000000 -0500
e51dac3
@@ -163,6 +163,7 @@
e51dac3
 if test $krb5_cv_sys_setpgrp_two = yes; then
e51dac3
   AC_DEFINE(SETPGRP_TWOARG,1,[Define if setpgrp takes two arguments])
e51dac3
 fi
e51dac3
+KRB5_USE_SELINUX
e51dac3
 dnl
e51dac3
 KRB5_NEED_PROTO([#include <stdlib.h>],unsetenv,1)
e51dac3
 dnl KRB5_NEED_PROTO([#include <stdlib.h>],setenv,1)
e51dac3
diff -ur krb5-1.6.3/src/config/pre.in krb5-1.6.3/src/config/pre.in
e51dac3
--- krb5-1.6.3/src/config/pre.in	2008-03-06 19:04:59.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/config/pre.in	2008-03-06 17:53:07.000000000 -0500
e51dac3
@@ -181,6 +181,7 @@
e51dac3
 CLNTLIBS = @CLNTLIBS@
e51dac3
 CLNTDEPLIBS = @CLNTDEPLIBS@
e51dac3
 PAM_LIBS = @PAM_LIBS@
e51dac3
+SELINUX_LIBS=@SELINUX_LIBS@
e51dac3
 
e51dac3
 INSTALL=@INSTALL@
e51dac3
 INSTALL_STRIP=
e51dac3
@@ -391,7 +392,7 @@
e51dac3
 # HESIOD_LIBS is -lhesiod...
e51dac3
 HESIOD_LIBS	= @HESIOD_LIBS@
e51dac3
 
e51dac3
-KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
e51dac3
+KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
e51dac3
 KRB4COMPAT_LIBS	= $(KRB4_LIB) $(DES425_LIB) $(KRB5_BASE_LIBS)
e51dac3
 KDB5_LIBS	= $(KDB5_LIB)
e51dac3
 GSS_LIBS	= $(GSS_KRB5_LIB)
e51dac3
diff -ur krb5-1.6.3/src/configure.in krb5-1.6.3/src/configure.in
e51dac3
--- krb5-1.6.3/src/configure.in	2008-03-06 19:04:59.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/configure.in	2008-03-06 17:39:53.000000000 -0500
e51dac3
@@ -945,6 +945,8 @@
e51dac3
 
e51dac3
 KRB5_WITH_PAM
e51dac3
 
e51dac3
+KRB5_WITH_SELINUX
e51dac3
+
e51dac3
 AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config])
e51dac3
 
e51dac3
 mansysconfdir=$sysconfdir
e51dac3
diff -ur krb5-1.6.3/src/include/autoconf.h.in krb5-1.6.3/src/include/autoconf.h.in
e51dac3
--- krb5-1.6.3/src/include/autoconf.h.in	2007-10-21 23:35:17.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/include/autoconf.h.in	2008-03-06 17:39:13.000000000 -0500
e51dac3
@@ -358,6 +358,9 @@
e51dac3
 /* Define to 1 if you have the `sched_yield' function. */
e51dac3
 #undef HAVE_SCHED_YIELD
e51dac3
 
e51dac3
+/* Define to 1 if you have the <selinux/selinux.h> header file. */
e51dac3
+#undef HAVE_SELINUX_SELINUX_H
e51dac3
+
e51dac3
 /* Define to 1 if you have the <semaphore.h> header file. */
e51dac3
 #undef HAVE_SEMAPHORE_H
e51dac3
 
e51dac3
@@ -370,6 +373,9 @@
e51dac3
 /* Define to 1 if you have the `setegid' function. */
e51dac3
 #undef HAVE_SETEGID
e51dac3
 
e51dac3
+/* Define to 1 if you have the `setfscreatecon' function. */
e51dac3
+#undef HAVE_SETFSCREATECON
e51dac3
+
e51dac3
 /* Define to 1 if you have the `setenv' function. */
e51dac3
 #undef HAVE_SETENV
e51dac3
 
e51dac3
@@ -695,6 +701,10 @@
e51dac3
 /* Define if the KDC should use a replay cache */
e51dac3
 #undef USE_RCACHE
e51dac3
 
e51dac3
+/* Define if Kerberos-aware tools should set SELinux file contexts when
e51dac3
+   creating files. */
e51dac3
+#undef USE_SELINUX
e51dac3
+
e51dac3
 /* Define if sigprocmask should be used */
e51dac3
 #undef USE_SIGPROCMASK
e51dac3
 
e51dac3
diff -ur krb5-1.6.3/src/include/k5-int.h krb5-1.6.3/src/include/k5-int.h
e51dac3
--- krb5-1.6.3/src/include/k5-int.h	2007-10-04 16:17:48.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/include/k5-int.h	2008-03-06 18:51:29.000000000 -0500
e51dac3
@@ -128,6 +128,20 @@
e51dac3
 typedef UINT64_TYPE krb5_ui_8;
e51dac3
 typedef INT64_TYPE krb5_int64;
e51dac3
 
e51dac3
+#include "k5-platform.h"
e51dac3
+
e51dac3
+#ifdef THREEPARAMOPEN
e51dac3
+#undef THREEPARAMOPEN
e51dac3
+#endif
e51dac3
+
e51dac3
+#ifdef USE_SELINUX
e51dac3
+#include "k5-label.h"
e51dac3
+#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z)
e51dac3
+#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y)
e51dac3
+#else
e51dac3
+#define WRITABLEFOPEN(x,y) fopen(x,y)
e51dac3
+#define THREEPARAMOPEN(x,y,z) open(x,y,z)
e51dac3
+#endif
e51dac3
 
e51dac3
 #define DEFAULT_PWD_STRING1 "Enter password"
e51dac3
 #define DEFAULT_PWD_STRING2 "Re-enter password for verification"
e51dac3
diff -ur krb5-1.6.3/src/include/krb5/krb5.hin krb5-1.6.3/src/include/krb5/krb5.hin
e51dac3
--- krb5-1.6.3/src/include/krb5/krb5.hin	2007-09-17 23:36:09.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/include/krb5/krb5.hin	2008-03-06 18:17:29.000000000 -0500
e51dac3
@@ -91,6 +91,12 @@
e51dac3
 #define THREEPARAMOPEN(x,y,z) open(x,y,z)
e51dac3
 #endif
e51dac3
 
e51dac3
+#if KRB5_PRIVATE
e51dac3
+#ifndef WRITABLEFOPEN
e51dac3
+#define WRITABLEFOPEN(x,y) fopen(x,y)
e51dac3
+#endif
e51dac3
+#endif
e51dac3
+
e51dac3
 #define KRB5_OLD_CRYPTO
e51dac3
 
e51dac3
 #include <stdlib.h>
e51dac3
diff -ur krb5-1.6.3/src/kadmin/dbutil/dump.c krb5-1.6.3/src/kadmin/dbutil/dump.c
e51dac3
--- krb5-1.6.3/src/kadmin/dbutil/dump.c	2006-12-18 18:11:15.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/kadmin/dbutil/dump.c	2008-03-06 18:33:44.000000000 -0500
e51dac3
@@ -1148,7 +1148,7 @@
e51dac3
 	 * want to get into.
e51dac3
 	 */
e51dac3
 	unlink(ofile);
e51dac3
-	if (!(f = fopen(ofile, "w"))) {
e51dac3
+	if (!(f = WRITABLEFOPEN(ofile, "w"))) {
e51dac3
 	    fprintf(stderr, ofopen_error,
e51dac3
 		    programname, ofile, error_message(errno));
e51dac3
 	    exit_status++;
e51dac3
diff -ur krb5-1.6.3/src/kadmin/dbutil/dumpv4.c krb5-1.6.3/src/kadmin/dbutil/dumpv4.c
e51dac3
--- krb5-1.6.3/src/kadmin/dbutil/dumpv4.c	2002-11-05 19:42:57.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/kadmin/dbutil/dumpv4.c	2008-03-06 18:33:50.000000000 -0500
e51dac3
@@ -324,7 +324,7 @@
e51dac3
 		 * want to get into.
e51dac3
 		 */
e51dac3
 		unlink(outname);
e51dac3
-		if (!(f = fopen(outname, "w"))) {
e51dac3
+		if (!(f = WRITABLEFOPEN(outname, "w"))) {
e51dac3
 			com_err(argv[0], errno,
e51dac3
 				"While opening file %s for writing", outname);
e51dac3
 			exit_status++;
e51dac3
diff -ur krb5-1.6.3/src/kadmin/ktutil/ktutil_funcs.c krb5-1.6.3/src/kadmin/ktutil/ktutil_funcs.c
e51dac3
--- krb5-1.6.3/src/kadmin/ktutil/ktutil_funcs.c	2005-10-12 16:48:36.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/kadmin/ktutil/ktutil_funcs.c	2008-03-06 18:34:19.000000000 -0500
e51dac3
@@ -520,7 +520,7 @@
e51dac3
     umask(0077); /*Changing umask for all of ktutil is OK
e51dac3
 		  * We don't ever write out anything that should use
e51dac3
 		  * default umask.*/
e51dac3
-    fp = fopen(name, "w");
e51dac3
+    fp = WRITABLEFOPEN(name, "w");
e51dac3
     if (!fp) {
e51dac3
 	retval = EIO;
e51dac3
 	goto free_pruned;
e51dac3
diff -ur krb5-1.6.3/src/krb5-config.in krb5-1.6.3/src/krb5-config.in
e51dac3
--- krb5-1.6.3/src/krb5-config.in	2006-06-15 20:26:49.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/krb5-config.in	2008-03-06 17:29:57.000000000 -0500
e51dac3
@@ -39,6 +39,7 @@
e51dac3
 RPATH_FLAG='@RPATH_FLAG@'
e51dac3
 PTHREAD_CFLAGS='@PTHREAD_CFLAGS@'
e51dac3
 DL_LIB='@DL_LIB@'
e51dac3
+SELINUX_LIBS='@SELINUX_LIBS@'
e51dac3
 
e51dac3
 LIBS='@LIBS@'
e51dac3
 GEN_LIB=@GEN_LIB@
e51dac3
@@ -217,7 +218,7 @@
e51dac3
     fi
e51dac3
 
e51dac3
     if test $library = 'krb5'; then
e51dac3
-	lib_flags="$lib_flags -lkrb5 -lk5crypto -lcom_err $GEN_LIB $LIBS $DL_LIB"
e51dac3
+	lib_flags="$lib_flags -lkrb5 -lk5crypto -lcom_err $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB"
e51dac3
     fi
e51dac3
 
e51dac3
     echo $lib_flags
e51dac3
diff -ur krb5-1.6.3/src/lib/kadm5/logger.c krb5-1.6.3/src/lib/kadm5/logger.c
e51dac3
--- krb5-1.6.3/src/lib/kadm5/logger.c	2007-04-04 17:08:05.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/lib/kadm5/logger.c	2008-03-06 18:30:32.000000000 -0500
e51dac3
@@ -425,7 +425,7 @@
e51dac3
 		     * Check for append/overwrite, then open the file.
e51dac3
 		     */
e51dac3
 		    if (cp[4] == ':' || cp[4] == '=') {
e51dac3
-			f = fopen(&cp[5], (cp[4] == ':') ? "a+" : "w");
e51dac3
+			f = WRITABLEFOPEN(&cp[5], (cp[4] == ':') ? "a+" : "w");
e51dac3
 			if (f) {
e51dac3
 			    log_control.log_entries[i].lfu_filep = f;
e51dac3
 			    log_control.log_entries[i].log_type = K_LOG_FILE;
e51dac3
@@ -959,7 +959,7 @@
e51dac3
 	     * In case the old logfile did not get moved out of the
e51dac3
 	     * way, open for append to prevent squashing the old logs.
e51dac3
 	     */
e51dac3
-	    f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
e51dac3
+	    f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+");
e51dac3
 	    if (f) {
e51dac3
 		log_control.log_entries[lindex].lfu_filep = f;
e51dac3
 	    } else {
e51dac3
diff -ur krb5-1.6.3/src/lib/kdb/kdb_default.c krb5-1.6.3/src/lib/kdb/kdb_default.c
e51dac3
--- krb5-1.6.3/src/lib/kdb/kdb_default.c	2006-10-11 22:39:14.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/lib/kdb/kdb_default.c	2008-03-06 18:31:18.000000000 -0500
e51dac3
@@ -161,9 +161,9 @@
e51dac3
     oumask = umask(077);
e51dac3
 #endif
e51dac3
 #ifdef ANSI_STDIO
e51dac3
-    if (!(kf = fopen(keyfile, "wb")))
e51dac3
+    if (!(kf = WRITABLEFOPEN(keyfile, "wb")))
e51dac3
 #else
e51dac3
-    if (!(kf = fopen(keyfile, "w")))
e51dac3
+    if (!(kf = WRITABLEFOPEN(keyfile, "w")))
e51dac3
 #endif
e51dac3
     {
e51dac3
 	int e = errno;
e51dac3
diff -ur krb5-1.6.3/src/lib/krb4/klog.c krb5-1.6.3/src/lib/krb4/klog.c
e51dac3
--- krb5-1.6.3/src/lib/krb4/klog.c	2006-03-11 17:23:28.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/lib/krb4/klog.c	2008-03-06 18:48:01.000000000 -0500
e51dac3
@@ -24,6 +24,7 @@
e51dac3
  * or implied warranty.
e51dac3
  */
e51dac3
 
e51dac3
+#include "k5-int.h"
e51dac3
 #include "krb.h"
e51dac3
 #include "autoconf.h"
e51dac3
 #ifdef HAVE_TIME_H
e51dac3
@@ -96,7 +97,7 @@
e51dac3
     if (!logtype_array[type])
e51dac3
 	return(logtxt);
e51dac3
 
e51dac3
-    if ((logfile = fopen(log_name,"a")) == NULL)
e51dac3
+    if ((logfile = WRITABLEFOPEN(log_name,"a")) == NULL)
e51dac3
         return(logtxt);
e51dac3
 
e51dac3
     (void) time(&now;;
e51dac3
diff -ur krb5-1.6.3/src/lib/krb4/kparse.c krb5-1.6.3/src/lib/krb4/kparse.c
e51dac3
--- krb5-1.6.3/src/lib/krb4/kparse.c	2006-06-16 02:58:42.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/lib/krb4/kparse.c	2008-03-06 18:35:18.000000000 -0500
e51dac3
@@ -583,7 +583,7 @@
e51dac3
     FILE *fp;
e51dac3
 
e51dac3
     if (--argc) {
e51dac3
-        fp = fopen(*++argv,"ra");
e51dac3
+        fp = WRITABLEOPEN(*++argv,"ra");
e51dac3
         if (fp == (FILE *)NULL) {
e51dac3
             fprintf(stderr,"can\'t open \"%s\"\n",*argv);
e51dac3
         }
e51dac3
diff -ur krb5-1.6.3/src/lib/krb4/log.c krb5-1.6.3/src/lib/krb4/log.c
e51dac3
--- krb5-1.6.3/src/lib/krb4/log.c	2006-03-11 17:23:28.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/lib/krb4/log.c	2008-03-06 18:47:49.000000000 -0500
e51dac3
@@ -30,6 +30,7 @@
e51dac3
    krb_set_logfile, or change all the invokers. */
e51dac3
 #endif
e51dac3
 
e51dac3
+#include "k5-int.h"
e51dac3
 #include "krb.h"
e51dac3
 #include "autoconf.h"
e51dac3
 #ifdef HAVE_TIME_H
e51dac3
@@ -79,7 +80,7 @@
e51dac3
 
e51dac3
     va_start(args, format);
e51dac3
 
e51dac3
-    if ((logfile = fopen(log_name,"a")) != NULL) {
e51dac3
+    if ((logfile = WRITABLEFOPEN(log_name,"a")) != NULL) {
e51dac3
 	(void) time(&now;;
e51dac3
 	tm = localtime(&now;;
e51dac3
 
e51dac3
diff -ur krb5-1.6.3/src/lib/krb5/keytab/kt_file.c krb5-1.6.3/src/lib/krb5/keytab/kt_file.c
e51dac3
--- krb5-1.6.3/src/lib/krb5/keytab/kt_file.c	2007-08-31 17:38:41.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/lib/krb5/keytab/kt_file.c	2008-03-06 18:19:56.000000000 -0500
e51dac3
@@ -1062,7 +1062,7 @@
e51dac3
 
e51dac3
     KTCHECKLOCK(id);
e51dac3
     errno = 0;
e51dac3
-    KTFILEP(id) = fopen(KTFILENAME(id),
e51dac3
+    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id),
e51dac3
 			(mode == KRB5_LOCKMODE_EXCLUSIVE) ?
e51dac3
 			  fopen_mode_rbplus : fopen_mode_rb);
e51dac3
     if (!KTFILEP(id)) {
e51dac3
@@ -1070,7 +1070,7 @@
e51dac3
 	    /* try making it first time around */
e51dac3
             krb5_create_secure_file(context, KTFILENAME(id));
e51dac3
 	    errno = 0;
e51dac3
-	    KTFILEP(id) = fopen(KTFILENAME(id), fopen_mode_rbplus);
e51dac3
+	    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), fopen_mode_rbplus);
e51dac3
 	    if (!KTFILEP(id))
e51dac3
 		return errno ? errno : EMFILE;
e51dac3
 	    writevno = 1;
e51dac3
diff -ur krb5-1.6.3/src/plugins/kdb/db2/libdb2/btree/bt_open.c krb5-1.6.3/src/plugins/kdb/db2/libdb2/btree/bt_open.c
e51dac3
--- krb5-1.6.3/src/plugins/kdb/db2/libdb2/btree/bt_open.c	2000-07-02 23:43:42.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/plugins/kdb/db2/libdb2/btree/bt_open.c	2008-03-06 18:27:37.000000000 -0500
e51dac3
@@ -58,6 +58,7 @@
e51dac3
 #include <string.h>
e51dac3
 #include <unistd.h>
e51dac3
 
e51dac3
+#include <k5-int.h>
e51dac3
 #include "db-int.h"
e51dac3
 #include "btree.h"
e51dac3
 
e51dac3
@@ -201,7 +202,7 @@
e51dac3
 			goto einval;
e51dac3
 		}
e51dac3
 		
e51dac3
-		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
e51dac3
+		if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
e51dac3
 			goto err;
e51dac3
 
e51dac3
 	} else {
e51dac3
diff -ur krb5-1.6.3/src/plugins/kdb/db2/libdb2/hash/hash.c krb5-1.6.3/src/plugins/kdb/db2/libdb2/hash/hash.c
e51dac3
--- krb5-1.6.3/src/plugins/kdb/db2/libdb2/hash/hash.c	2006-06-14 22:35:44.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/plugins/kdb/db2/libdb2/hash/hash.c	2008-03-06 18:29:17.000000000 -0500
e51dac3
@@ -51,6 +51,7 @@
e51dac3
 #include <assert.h>
e51dac3
 #endif
e51dac3
 
e51dac3
+#include <k5-int.h>
e51dac3
 #include "db-int.h"
e51dac3
 #include "hash.h"
e51dac3
 #include "page.h"
e51dac3
@@ -140,7 +141,7 @@
e51dac3
 		new_table = 1;
e51dac3
 	}
e51dac3
 	if (file) {
e51dac3
-		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
e51dac3
+		if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1)
e51dac3
 			RETURN_ERROR(errno, error0);
e51dac3
 		(void)fcntl(hashp->fp, F_SETFD, 1);
e51dac3
 	}
e51dac3
diff -ur krb5-1.6.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c krb5-1.6.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c
e51dac3
--- krb5-1.6.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c	1998-01-21 11:33:31.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c	2008-03-06 18:27:01.000000000 -0500
e51dac3
@@ -51,6 +51,7 @@
e51dac3
 #include <stdio.h>
e51dac3
 #include <unistd.h>
e51dac3
 
e51dac3
+#include <k5-int.h>
e51dac3
 #include "db-int.h"
e51dac3
 #include "recno.h"
e51dac3
 
e51dac3
@@ -68,7 +69,7 @@
e51dac3
 	int rfd, sverrno;
e51dac3
 
e51dac3
 	/* Open the user's file -- if this fails, we're done. */
e51dac3
-	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
e51dac3
+	if (fname != NULL && (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
e51dac3
 		return (NULL);
e51dac3
 
e51dac3
 	/* Create a btree in memory (backed by disk). */
e51dac3
diff -ur krb5-1.6.3/src/util/profile/prof_file.c krb5-1.6.3/src/util/profile/prof_file.c
e51dac3
--- krb5-1.6.3/src/util/profile/prof_file.c	2005-10-21 16:03:44.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/util/profile/prof_file.c	2008-03-06 19:02:44.000000000 -0500
e51dac3
@@ -29,6 +29,7 @@
e51dac3
 #endif
e51dac3
 
e51dac3
 #include "k5-platform.h"
e51dac3
+#include "k5-int.h"
e51dac3
 
e51dac3
 struct global_shared_profile_data {
e51dac3
 	/* This is the head of the global list of shared trees */
e51dac3
@@ -419,7 +420,7 @@
e51dac3
 
e51dac3
 	errno = 0;
e51dac3
 
e51dac3
-	f = fopen(new_file, "w");
e51dac3
+	f = WRITABLEFOPEN(new_file, "w");
e51dac3
 	if (!f) {
e51dac3
 		retval = errno;
e51dac3
 		if (retval == 0)
e51dac3
diff -ur krb5-1.6.3/src/util/support/libkrb5support.exports krb5-1.6.3/src/util/support/libkrb5support.exports
e51dac3
--- krb5-1.6.3/src/util/support/libkrb5support.exports	2006-05-04 14:35:01.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/util/support/libkrb5support.exports	2008-03-06 17:33:30.000000000 -0500
e51dac3
@@ -32,3 +32,6 @@
e51dac3
 krb5int_clear_error
e51dac3
 krb5int_set_error_info_callout_fn
e51dac3
 krb5int_gmt_mktime
e51dac3
+krb5int_labeled_open
e51dac3
+krb5int_labeled_fopen
e51dac3
+krb5int_labeled_creat
e51dac3
diff -ur krb5-1.6.3/src/util/support/Makefile.in krb5-1.6.3/src/util/support/Makefile.in
e51dac3
--- krb5-1.6.3/src/util/support/Makefile.in	2006-10-17 23:15:24.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/util/support/Makefile.in	2008-03-06 17:33:30.000000000 -0500
e51dac3
@@ -27,6 +27,7 @@
e51dac3
 
e51dac3
 STLIBOBJS= \
e51dac3
 	threads.o \
e51dac3
+	selinux.o \
e51dac3
 	init-addrinfo.o \
e51dac3
 	plugins.o \
e51dac3
 	errors.o \
e51dac3
@@ -55,7 +56,7 @@
e51dac3
 	$(srcdir)/fake-addrinfo.c
e51dac3
 SHLIB_EXPDEPS =
e51dac3
 # Add -lm if dumping thread stats, for sqrt.
e51dac3
-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
e51dac3
+SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
e51dac3
 SHLIB_DIRS=
e51dac3
 SHLIB_RDIRS=$(KRB5_LIBDIR)
e51dac3
 
e51dac3
--- krb5-1.6.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c	2008-03-06 19:20:37.000000000 -0500
e51dac3
+++ krb5-1.6.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c	2008-03-06 19:20:28.000000000 -0500
e51dac3
@@ -1083,7 +1083,7 @@
e51dac3
 
e51dac3
     /* Create a temporary file which contains all the entries except the
e51dac3
        entry for the given service dn */
e51dac3
-    pfile = fopen(file_name, "r+");
e51dac3
+    pfile = WRITABLEFOPEN(file_name, "r+");
e51dac3
     if (pfile == NULL) {
e51dac3
 	com_err(me, errno, "while deleting entry from file %s", file_name);
e51dac3
 	goto cleanup;
e51dac3
@@ -1764,7 +1764,7 @@
e51dac3
 
e51dac3
     /* TODO: file lock for the service password file */
e51dac3
     /* set password in the file */
e51dac3
-    pfile = fopen(file_name, "r+");
e51dac3
+    pfile = WRITABLEFOPEN(file_name, "r+");
e51dac3
     if (pfile == NULL) {
e51dac3
 	com_err(me, errno, "Failed to open file %s", file_name);
e51dac3
 	goto cleanup;
e51dac3
@@ -1806,7 +1806,7 @@
e51dac3
 	sprintf(tmp_file,"%s.%s",file_name,"tmp");
e51dac3
 
e51dac3
 	omask = umask(077);
e51dac3
-	newfile = fopen(tmp_file, "w+");
e51dac3
+	newfile = WRITABLEFOPEN(tmp_file, "w+");
e51dac3
 	umask(omask);
e51dac3
 	if (newfile == NULL) {
e51dac3
 	    com_err(me, errno, "Error creating file %s", tmp_file);
e51dac3
@@ -2031,7 +2031,7 @@
e51dac3
 
e51dac3
     /* set password in the file */
e51dac3
     old_mode = umask(0177);
e51dac3
-    pfile = fopen(file_name, "a+");
e51dac3
+    pfile = WRITABLEFOPEN(file_name, "a+");
e51dac3
     if (pfile == NULL) {
e51dac3
 	com_err(me, errno, "Failed to open file %s: %s", file_name,
e51dac3
 		strerror (errno));
e51dac3
@@ -2082,7 +2082,7 @@
e51dac3
 	sprintf(tmp_file,"%s.%s",file_name,"tmp");
e51dac3
 
e51dac3
 	omask = umask(077);
e51dac3
-	newfile = fopen(tmp_file, "w");
e51dac3
+	newfile = WRITABLEFOPEN(tmp_file, "w");
e51dac3
 	umask (omask);
e51dac3
 	if (newfile == NULL) {
e51dac3
 	    com_err(me, errno, "Error creating file %s", tmp_file);
e51dac3
--- krb5-1.6.3/src/util/support/selinux.c	2007-08-25 03:19:00.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/util/support/selinux.c	2007-08-24 23:38:39.000000000 -0400
e51dac3
@@ -0,0 +1,256 @@
e51dac3
+/*
e51dac3
+ * Copyright 2007,2008 Red Hat, Inc.  All Rights Reserved.
e51dac3
+ *
e51dac3
+ * Redistribution and use in source and binary forms, with or without
e51dac3
+ * modification, are permitted provided that the following conditions are met:
e51dac3
+ *
e51dac3
+ *  Redistributions of source code must retain the above copyright notice, this
e51dac3
+ *  list of conditions and the following disclaimer.
e51dac3
+ *
e51dac3
+ *  Redistributions in binary form must reproduce the above copyright notice,
e51dac3
+ *  this list of conditions and the following disclaimer in the documentation
e51dac3
+ *  and/or other materials provided with the distribution.
e51dac3
+ *
e51dac3
+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
e51dac3
+ *  used to endorse or promote products derived from this software without
e51dac3
+ *  specific prior written permission.
e51dac3
+ *
e51dac3
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
e51dac3
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
e51dac3
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
e51dac3
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
e51dac3
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
e51dac3
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
e51dac3
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
e51dac3
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
e51dac3
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
e51dac3
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
e51dac3
+ * POSSIBILITY OF SUCH DAMAGE.
e51dac3
+ * 
e51dac3
+ * File-opening wrappers for creating correctly-labeled files.  So far, we can
e51dac3
+ * assume that this is Linux-specific, so we make many simplifying assumptions.
e51dac3
+ */
e51dac3
+
e51dac3
+#include "../../include/autoconf.h"
e51dac3
+
e51dac3
+#ifdef USE_SELINUX
e51dac3
+
e51dac3
+#include <k5-label.h>
e51dac3
+#include <sys/types.h>
e51dac3
+#include <sys/stat.h>
e51dac3
+#include <errno.h>
e51dac3
+#include <fcntl.h>
e51dac3
+#include <limits.h>
e51dac3
+#include <pthread.h>
e51dac3
+#include <stdarg.h>
e51dac3
+#include <stdio.h>
e51dac3
+#include <stdlib.h>
e51dac3
+#include <string.h>
e51dac3
+#include <unistd.h>
e51dac3
+#include <selinux/selinux.h>
e51dac3
+
e51dac3
+/* #define DEBUG 1 */
e51dac3
+
e51dac3
+static pthread_mutex_t labeled_lock = PTHREAD_MUTEX_INITIALIZER;
e51dac3
+
e51dac3
+static security_context_t
e51dac3
+push_fscreatecon(const char *pathname, mode_t mode)
e51dac3
+{
e51dac3
+	security_context_t previous, next;
e51dac3
+	const char *fullpath;
e51dac3
+
e51dac3
+	previous = NULL;
e51dac3
+	if (is_selinux_enabled()) {
e51dac3
+		if (getfscreatecon(&previous) == 0) {
e51dac3
+			char *genpath;
e51dac3
+			genpath = NULL;
e51dac3
+			if (pathname[0] != '/') {
e51dac3
+				char *wd;
e51dac3
+				size_t len;
e51dac3
+				len = 0;
e51dac3
+				wd = getcwd(NULL, len);
e51dac3
+				if (wd == NULL) {
e51dac3
+					if (previous != NULL) {
e51dac3
+						freecon(previous);
e51dac3
+					}
e51dac3
+					return NULL;
e51dac3
+				}
e51dac3
+				len = strlen(wd) + 1 + strlen(pathname) + 1;
e51dac3
+				genpath = malloc(len);
e51dac3
+				if (genpath == NULL) {
e51dac3
+					free(wd);
e51dac3
+					if (previous != NULL) {
e51dac3
+						freecon(previous);
e51dac3
+					}
e51dac3
+					return NULL;
e51dac3
+				}
e51dac3
+				sprintf(genpath, "%s/%s", wd, pathname);
e51dac3
+				free(wd);
e51dac3
+				fullpath = genpath;
e51dac3
+			} else {
e51dac3
+				fullpath = pathname;
e51dac3
+			}
e51dac3
+			next = NULL;
e51dac3
+#ifdef DEBUG
e51dac3
+			if (isatty(fileno(stderr))) {
e51dac3
+				fprintf(stderr, "Looking up context for "
e51dac3
+					"\"%s\"(%05o).\n", fullpath, mode);
e51dac3
+			}
e51dac3
+#endif
e51dac3
+			if (matchpathcon(fullpath, mode, &next) != 0) {
e51dac3
+				free(genpath);
e51dac3
+				if (previous != NULL) {
e51dac3
+					freecon(previous);
e51dac3
+				}
e51dac3
+				return NULL;
e51dac3
+			}
e51dac3
+			free(genpath);
e51dac3
+#ifdef DEBUG
e51dac3
+			if (isatty(fileno(stderr))) {
e51dac3
+				fprintf(stderr, "Setting file creation context "
e51dac3
+					"to \"%s\".\n", next);
e51dac3
+			}
e51dac3
+#endif
e51dac3
+			if (setfscreatecon(next) != 0) {
e51dac3
+				freecon(next);
e51dac3
+				if (previous != NULL) {
e51dac3
+					freecon(previous);
e51dac3
+				}
e51dac3
+				return NULL;
e51dac3
+			}
e51dac3
+			freecon(next);
e51dac3
+#ifdef DEBUG
e51dac3
+		} else {
e51dac3
+			if (isatty(fileno(stderr))) {
e51dac3
+				fprintf(stderr, "Unable to determine "
e51dac3
+					"current context.\n");
e51dac3
+			}
e51dac3
+#endif
e51dac3
+		}
e51dac3
+	}
e51dac3
+	return previous;
e51dac3
+}
e51dac3
+
e51dac3
+static void
e51dac3
+pop_fscreatecon(security_context_t previous)
e51dac3
+{
e51dac3
+	if (is_selinux_enabled()) {
e51dac3
+#ifdef DEBUG
e51dac3
+		if (isatty(fileno(stderr))) {
e51dac3
+			if (previous != NULL) {
e51dac3
+				fprintf(stderr, "Resetting file creation "
e51dac3
+					"context to \"%s\".\n", previous);
e51dac3
+			} else {
e51dac3
+				fprintf(stderr, "Resetting file creation "
e51dac3
+					"context to default.\n");
e51dac3
+			}
e51dac3
+		}
e51dac3
+#endif
e51dac3
+		setfscreatecon(previous);
e51dac3
+		if (previous != NULL) {
e51dac3
+			freecon(previous);
e51dac3
+		}
e51dac3
+	}
e51dac3
+}
e51dac3
+
e51dac3
+FILE *
e51dac3
+krb5int_labeled_fopen(const char *path, const char *mode)
e51dac3
+{
e51dac3
+	FILE *fp;
e51dac3
+	int errno_save;
e51dac3
+	security_context_t ctx;
e51dac3
+
e51dac3
+	pthread_mutex_lock(&labeled_lock);
e51dac3
+	ctx = push_fscreatecon(path, 0);
e51dac3
+	fp = fopen(path, mode);
e51dac3
+	errno_save = errno;
e51dac3
+	pop_fscreatecon(ctx);
e51dac3
+	pthread_mutex_unlock(&labeled_lock);
e51dac3
+
e51dac3
+	errno = errno_save;
e51dac3
+	return fp;
e51dac3
+}
e51dac3
+
e51dac3
+int
e51dac3
+krb5int_labeled_creat(const char *path, mode_t mode)
e51dac3
+{
e51dac3
+	int fd;
e51dac3
+	int errno_save;
e51dac3
+	security_context_t ctx;
e51dac3
+
e51dac3
+	pthread_mutex_lock(&labeled_lock);
e51dac3
+	ctx = push_fscreatecon(path, 0);
e51dac3
+	fd = creat(path, mode);
e51dac3
+	errno_save = errno;
e51dac3
+	pop_fscreatecon(ctx);
e51dac3
+	pthread_mutex_unlock(&labeled_lock);
e51dac3
+
e51dac3
+	errno = errno_save;
e51dac3
+	return fd;
e51dac3
+}
e51dac3
+
e51dac3
+int
e51dac3
+krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
e51dac3
+{
e51dac3
+	int ret;
e51dac3
+	int errno_save;
e51dac3
+	security_context_t ctx;
e51dac3
+
e51dac3
+	pthread_mutex_lock(&labeled_lock);
e51dac3
+	ctx = push_fscreatecon(path, mode);
e51dac3
+	ret = mknod(path, mode, dev);
e51dac3
+	errno_save = errno;
e51dac3
+	pop_fscreatecon(ctx);
e51dac3
+	pthread_mutex_unlock(&labeled_lock);
e51dac3
+
e51dac3
+	errno = errno_save;
e51dac3
+	return ret;
e51dac3
+}
e51dac3
+
e51dac3
+int
e51dac3
+krb5int_labeled_mkdir(const char *path, mode_t mode)
e51dac3
+{
e51dac3
+	int ret;
e51dac3
+	int errno_save;
e51dac3
+	security_context_t ctx;
e51dac3
+
e51dac3
+	pthread_mutex_lock(&labeled_lock);
e51dac3
+	ctx = push_fscreatecon(path, S_IFDIR);
e51dac3
+	ret = mkdir(path, mode);
e51dac3
+	errno_save = errno;
e51dac3
+	pop_fscreatecon(ctx);
e51dac3
+	pthread_mutex_unlock(&labeled_lock);
e51dac3
+
e51dac3
+	errno = errno_save;
e51dac3
+	return ret;
e51dac3
+}
e51dac3
+
e51dac3
+int
e51dac3
+krb5int_labeled_open(const char *path, int flags, ...)
e51dac3
+{
e51dac3
+	int fd;
e51dac3
+	int errno_save;
e51dac3
+	security_context_t ctx;
e51dac3
+	mode_t mode;
e51dac3
+	va_list ap;
e51dac3
+
e51dac3
+	if ((flags & O_CREAT) == 0) {
e51dac3
+		return open(path, flags);
e51dac3
+	}
e51dac3
+
e51dac3
+	pthread_mutex_lock(&labeled_lock);
e51dac3
+	ctx = push_fscreatecon(path, 0);
e51dac3
+
e51dac3
+	va_start(ap, flags);
e51dac3
+	mode = va_arg(ap, mode_t);
e51dac3
+	fd = open(path, flags, mode);
e51dac3
+	va_end(ap);
e51dac3
+
e51dac3
+	errno_save = errno;
e51dac3
+
e51dac3
+	pop_fscreatecon(ctx);
e51dac3
+	pthread_mutex_unlock(&labeled_lock);
e51dac3
+	return fd;
e51dac3
+}
e51dac3
+
e51dac3
+#endif
e51dac3
--- krb5-1.6.3/src/include/k5-label.h	2007-08-25 03:19:00.000000000 -0400
e51dac3
+++ krb5-1.6.3/src/include/k5-label.h	2007-08-25 03:00:02.000000000 -0400
e51dac3
@@ -0,0 +1,17 @@
e51dac3
+#ifndef _KRB5_LABEL_H
e51dac3
+#define _KRB5_LABEL_H
e51dac3
+/* Wrapper functions which help us create files and directories with the right
e51dac3
+ * context labels. */
e51dac3
+#ifdef USE_SELINUX
e51dac3
+#include <sys/types.h>
e51dac3
+#include <sys/stat.h>
e51dac3
+#include <fcntl.h>
e51dac3
+#include <stdio.h>
e51dac3
+#include <unistd.h>
e51dac3
+FILE *krb5int_labeled_fopen(const char *path, const char *mode);
e51dac3
+int krb5int_labeled_creat(const char *path, mode_t mode);
e51dac3
+int krb5int_labeled_open(const char *path, int flags, ...);
e51dac3
+int krb5int_labeled_mkdir(const char *path, mode_t mode);
e51dac3
+int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device);
e51dac3
+#endif
e51dac3
+#endif