You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1038 lines
32 KiB
1038 lines
32 KiB
From 021f1f1bf690694945a3ab0a5221797a7bcd6a99 Mon Sep 17 00:00:00 2001 |
|
From: Robbie Harwood <rharwood@redhat.com> |
|
Date: Tue, 23 Aug 2016 16:30:53 -0400 |
|
Subject: [PATCH] [downstream] SELinux integration |
|
|
|
SELinux bases access to files on the domain of the requesting process, |
|
the operation being performed, and the context applied to the file. |
|
|
|
In many cases, applications needn't be SELinux aware to work properly, |
|
because SELinux can apply a default label to a file based on the label |
|
of the directory in which it's created. |
|
|
|
In the case of files such as /etc/krb5.keytab, however, this isn't |
|
sufficient, as /etc/krb5.keytab will almost always need to be given a |
|
label which differs from that of /etc/issue or /etc/resolv.conf. The |
|
the kdb stash file needs a different label than the database for which |
|
it's holding a master key, even though both typically live in the same |
|
directory. |
|
|
|
To give the file the correct label, we can either force a "restorecon" |
|
call to fix a file's label after it's created, or create the file with |
|
the right label, as we attempt to do here. We lean on THREEPARAMOPEN |
|
and define a similar macro named WRITABLEFOPEN with which we replace |
|
several uses of fopen(). |
|
|
|
The file creation context that we're manipulating here is a process-wide |
|
attribute. While for the most part, applications which need to label |
|
files when they're created have tended to be single-threaded, there's |
|
not much we can do to avoid interfering with an application that |
|
manipulates the creation context directly. Right now we're mediating |
|
access using a library-local mutex, but that can only work for consumers |
|
that are part of this package -- an unsuspecting application will still |
|
stomp all over us. |
|
|
|
The selabel APIs for looking up the context should be thread-safe (per |
|
Red Hat #273081), so switching to using them instead of matchpathcon(), |
|
which we used earlier, is some improvement. |
|
|
|
Last-updated: krb5-1.20.1 |
|
[jrische@redhat.com: Replace deprecated security_context_t by char *: |
|
- src/util/support/selinux.c] |
|
--- |
|
src/aclocal.m4 | 48 +++ |
|
src/build-tools/krb5-config.in | 3 +- |
|
src/config/pre.in | 3 +- |
|
src/configure.ac | 2 + |
|
src/include/k5-int.h | 1 + |
|
src/include/k5-label.h | 32 ++ |
|
src/include/krb5/krb5.hin | 6 + |
|
src/kadmin/dbutil/dump.c | 11 +- |
|
src/kdc/main.c | 2 +- |
|
src/kprop/kpropd.c | 9 + |
|
src/lib/kadm5/logger.c | 4 +- |
|
src/lib/kdb/kdb_log.c | 2 +- |
|
src/lib/krb5/ccache/cc_dir.c | 26 +- |
|
src/lib/krb5/keytab/kt_file.c | 4 +- |
|
src/lib/krb5/os/trace.c | 2 +- |
|
src/plugins/kdb/db2/adb_openclose.c | 2 +- |
|
src/plugins/kdb/db2/kdb_db2.c | 4 +- |
|
src/plugins/kdb/db2/libdb2/btree/bt_open.c | 3 +- |
|
src/plugins/kdb/db2/libdb2/hash/hash.c | 3 +- |
|
src/plugins/kdb/db2/libdb2/recno/rec_open.c | 4 +- |
|
.../kdb/ldap/ldap_util/kdb5_ldap_services.c | 11 +- |
|
src/util/profile/prof_file.c | 3 +- |
|
src/util/support/Makefile.in | 3 +- |
|
src/util/support/selinux.c | 405 ++++++++++++++++++ |
|
24 files changed, 572 insertions(+), 21 deletions(-) |
|
create mode 100644 src/include/k5-label.h |
|
create mode 100644 src/util/support/selinux.c |
|
|
|
diff --git a/src/aclocal.m4 b/src/aclocal.m4 |
|
index ce3c5a9bac..3331970930 100644 |
|
--- a/src/aclocal.m4 |
|
+++ b/src/aclocal.m4 |
|
@@ -85,6 +85,7 @@ AC_SUBST_FILE(libnodeps_frag) |
|
dnl |
|
KRB5_AC_PRAGMA_WEAK_REF |
|
WITH_LDAP |
|
+KRB5_WITH_SELINUX |
|
KRB5_LIB_PARAMS |
|
KRB5_AC_INITFINI |
|
KRB5_AC_ENABLE_THREADS |
|
@@ -1526,4 +1527,51 @@ AC_SUBST(PAM_LIBS) |
|
AC_SUBST(PAM_MAN) |
|
AC_SUBST(NON_PAM_MAN) |
|
])dnl |
|
+dnl |
|
+dnl Use libselinux to set file contexts on newly-created files. |
|
+dnl |
|
+AC_DEFUN(KRB5_WITH_SELINUX,[ |
|
+AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])], |
|
+ withselinux="$withval",withselinux=auto) |
|
+old_LIBS="$LIBS" |
|
+if test "$withselinux" != no ; then |
|
+ AC_MSG_RESULT([checking for libselinux...]) |
|
+ SELINUX_LIBS= |
|
+ AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h) |
|
+ if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then |
|
+ if test "$withselinux" = auto ; then |
|
+ AC_MSG_RESULT([Unable to locate selinux/selinux.h.]) |
|
+ withselinux=no |
|
+ else |
|
+ AC_MSG_ERROR([Unable to locate selinux/selinux.h.]) |
|
+ fi |
|
+ fi |
|
|
|
+ LIBS= |
|
+ unset ac_cv_func_setfscreatecon |
|
+ AC_CHECK_FUNCS(setfscreatecon selabel_open) |
|
+ if test "x$ac_cv_func_setfscreatecon" = xno ; then |
|
+ AC_CHECK_LIB(selinux,setfscreatecon) |
|
+ unset ac_cv_func_setfscreatecon |
|
+ AC_CHECK_FUNCS(setfscreatecon selabel_open) |
|
+ if test "x$ac_cv_func_setfscreatecon" = xyes ; then |
|
+ SELINUX_LIBS="$LIBS" |
|
+ else |
|
+ if test "$withselinux" = auto ; then |
|
+ AC_MSG_RESULT([Unable to locate libselinux.]) |
|
+ withselinux=no |
|
+ else |
|
+ AC_MSG_ERROR([Unable to locate libselinux.]) |
|
+ fi |
|
+ fi |
|
+ fi |
|
+ if test "$withselinux" != no ; then |
|
+ AC_MSG_NOTICE([building with SELinux labeling support]) |
|
+ AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.]) |
|
+ SELINUX_LIBS="$LIBS" |
|
+ EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon" |
|
+ fi |
|
+fi |
|
+LIBS="$old_LIBS" |
|
+AC_SUBST(SELINUX_LIBS) |
|
+])dnl |
|
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in |
|
index 8e6eb86601..7677f37359 100755 |
|
--- a/src/build-tools/krb5-config.in |
|
+++ b/src/build-tools/krb5-config.in |
|
@@ -40,6 +40,7 @@ DL_LIB='@DL_LIB@' |
|
DEFCCNAME='@DEFCCNAME@' |
|
DEFKTNAME='@DEFKTNAME@' |
|
DEFCKTNAME='@DEFCKTNAME@' |
|
+SELINUX_LIBS='@SELINUX_LIBS@' |
|
|
|
LIBS='@LIBS@' |
|
GEN_LIB=@GEN_LIB@ |
|
@@ -253,7 +254,7 @@ if test -n "$do_libs"; then |
|
fi |
|
|
|
# If we ever support a flag to generate output suitable for static |
|
- # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB" |
|
+ # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB" |
|
# here. |
|
|
|
echo $lib_flags |
|
diff --git a/src/config/pre.in b/src/config/pre.in |
|
index a0c60c70b3..7eaa2f351c 100644 |
|
--- a/src/config/pre.in |
|
+++ b/src/config/pre.in |
|
@@ -177,6 +177,7 @@ LD = $(PURE) @LD@ |
|
KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include |
|
LDFLAGS = @LDFLAGS@ |
|
LIBS = @LIBS@ |
|
+SELINUX_LIBS=@SELINUX_LIBS@ |
|
|
|
INSTALL=@INSTALL@ |
|
INSTALL_STRIP= |
|
@@ -379,7 +380,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME) |
|
# HESIOD_LIBS is -lhesiod... |
|
HESIOD_LIBS = @HESIOD_LIBS@ |
|
|
|
-KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB) |
|
+KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB) |
|
KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS) |
|
GSS_LIBS = $(GSS_KRB5_LIB) |
|
# needs fixing if ever used on macOS! |
|
diff --git a/src/configure.ac b/src/configure.ac |
|
index 587221936e..69be9030f8 100644 |
|
--- a/src/configure.ac |
|
+++ b/src/configure.ac |
|
@@ -1401,6 +1401,8 @@ AC_PATH_PROG(GROFF, groff) |
|
|
|
KRB5_WITH_PAM |
|
|
|
+KRB5_WITH_SELINUX |
|
+ |
|
# Make localedir work in autoconf 2.5x. |
|
if test "${localedir+set}" != set; then |
|
localedir='$(datadir)/locale' |
|
diff --git a/src/include/k5-int.h b/src/include/k5-int.h |
|
index 1d1c8293f4..768110e5ef 100644 |
|
--- a/src/include/k5-int.h |
|
+++ b/src/include/k5-int.h |
|
@@ -128,6 +128,7 @@ typedef unsigned char u_char; |
|
|
|
|
|
#include "k5-platform.h" |
|
+#include "k5-label.h" |
|
|
|
#define KRB5_KDB_MAX_LIFE (60*60*24) /* one day */ |
|
#define KRB5_KDB_MAX_RLIFE (60*60*24*7) /* one week */ |
|
diff --git a/src/include/k5-label.h b/src/include/k5-label.h |
|
new file mode 100644 |
|
index 0000000000..dfaaa847cb |
|
--- /dev/null |
|
+++ b/src/include/k5-label.h |
|
@@ -0,0 +1,32 @@ |
|
+#ifndef _KRB5_LABEL_H |
|
+#define _KRB5_LABEL_H |
|
+ |
|
+#ifdef THREEPARAMOPEN |
|
+#undef THREEPARAMOPEN |
|
+#endif |
|
+#ifdef WRITABLEFOPEN |
|
+#undef WRITABLEFOPEN |
|
+#endif |
|
+ |
|
+/* Wrapper functions which help us create files and directories with the right |
|
+ * context labels. */ |
|
+#ifdef USE_SELINUX |
|
+#include <sys/types.h> |
|
+#include <sys/stat.h> |
|
+#include <fcntl.h> |
|
+#include <stdio.h> |
|
+#include <unistd.h> |
|
+FILE *krb5int_labeled_fopen(const char *path, const char *mode); |
|
+int krb5int_labeled_creat(const char *path, mode_t mode); |
|
+int krb5int_labeled_open(const char *path, int flags, ...); |
|
+int krb5int_labeled_mkdir(const char *path, mode_t mode); |
|
+int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device); |
|
+#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z) |
|
+#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y) |
|
+void *krb5int_push_fscreatecon_for(const char *pathname); |
|
+void krb5int_pop_fscreatecon(void *previous); |
|
+#else |
|
+#define WRITABLEFOPEN(x,y) fopen(x,y) |
|
+#define THREEPARAMOPEN(x,y,z) open(x,y,z) |
|
+#endif |
|
+#endif |
|
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin |
|
index 9c76780181..dd6430ece8 100644 |
|
--- a/src/include/krb5/krb5.hin |
|
+++ b/src/include/krb5/krb5.hin |
|
@@ -87,6 +87,12 @@ |
|
#define THREEPARAMOPEN(x,y,z) open(x,y,z) |
|
#endif |
|
|
|
+#if KRB5_PRIVATE |
|
+#ifndef WRITABLEFOPEN |
|
+#define WRITABLEFOPEN(x,y) fopen(x,y) |
|
+#endif |
|
+#endif |
|
+ |
|
#define KRB5_OLD_CRYPTO |
|
|
|
#include <stdlib.h> |
|
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c |
|
index a89b5144f6..4d6cc0bdf9 100644 |
|
--- a/src/kadmin/dbutil/dump.c |
|
+++ b/src/kadmin/dbutil/dump.c |
|
@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname) |
|
{ |
|
int fd = -1; |
|
FILE *f; |
|
+#ifdef USE_SELINUX |
|
+ void *selabel; |
|
+#endif |
|
|
|
*tmpname = NULL; |
|
if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0) |
|
goto error; |
|
|
|
+#ifdef USE_SELINUX |
|
+ selabel = krb5int_push_fscreatecon_for(ofile); |
|
+#endif |
|
fd = mkstemp(*tmpname); |
|
+#ifdef USE_SELINUX |
|
+ krb5int_pop_fscreatecon(selabel); |
|
+#endif |
|
if (fd == -1) |
|
goto error; |
|
|
|
@@ -197,7 +206,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd_out) |
|
goto cleanup; |
|
} |
|
|
|
- fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
|
+ fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600); |
|
if (fd == -1) { |
|
com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok); |
|
goto cleanup; |
|
diff --git a/src/kdc/main.c b/src/kdc/main.c |
|
index bfdfef5c48..b43fe9a082 100644 |
|
--- a/src/kdc/main.c |
|
+++ b/src/kdc/main.c |
|
@@ -844,7 +844,7 @@ write_pid_file(const char *path) |
|
FILE *file; |
|
unsigned long pid; |
|
|
|
- file = fopen(path, "w"); |
|
+ file = WRITABLEFOPEN(path, "w"); |
|
if (file == NULL) |
|
return errno; |
|
pid = (unsigned long) getpid(); |
|
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c |
|
index aa3c81ea30..cb9785aaeb 100644 |
|
--- a/src/kprop/kpropd.c |
|
+++ b/src/kprop/kpropd.c |
|
@@ -488,6 +488,9 @@ doit(int fd) |
|
krb5_enctype etype; |
|
int database_fd; |
|
char host[INET6_ADDRSTRLEN + 1]; |
|
+#ifdef USE_SELINUX |
|
+ void *selabel; |
|
+#endif |
|
|
|
signal_wrapper(SIGALRM, alarm_handler); |
|
alarm(params.iprop_resync_timeout); |
|
@@ -543,9 +546,15 @@ doit(int fd) |
|
free(name); |
|
exit(1); |
|
} |
|
+#ifdef USE_SELINUX |
|
+ selabel = krb5int_push_fscreatecon_for(file); |
|
+#endif |
|
omask = umask(077); |
|
lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600); |
|
(void)umask(omask); |
|
+#ifdef USE_SELINUX |
|
+ krb5int_pop_fscreatecon(selabel); |
|
+#endif |
|
retval = krb5_lock_file(kpropd_context, lock_fd, |
|
KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK); |
|
if (retval) { |
|
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c |
|
index e14da53790..b879a4049b 100644 |
|
--- a/src/lib/kadm5/logger.c |
|
+++ b/src/lib/kadm5/logger.c |
|
@@ -310,7 +310,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do |
|
*/ |
|
append = (cp[4] == ':') ? O_APPEND : 0; |
|
if (append || cp[4] == '=') { |
|
- fd = open(&cp[5], O_CREAT | O_WRONLY | append, |
|
+ fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append, |
|
S_IRUSR | S_IWUSR | S_IRGRP); |
|
if (fd != -1) |
|
f = fdopen(fd, append ? "a" : "w"); |
|
@@ -777,7 +777,7 @@ krb5_klog_reopen(krb5_context kcontext) |
|
* In case the old logfile did not get moved out of the |
|
* way, open for append to prevent squashing the old logs. |
|
*/ |
|
- f = fopen(log_control.log_entries[lindex].lfu_fname, "a+"); |
|
+ f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+"); |
|
if (f) { |
|
set_cloexec_file(f); |
|
log_control.log_entries[lindex].lfu_filep = f; |
|
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c |
|
index 2659a25018..e9b95fce59 100644 |
|
--- a/src/lib/kdb/kdb_log.c |
|
+++ b/src/lib/kdb/kdb_log.c |
|
@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries) |
|
return ENOMEM; |
|
|
|
if (stat(logname, &st) == -1) { |
|
- log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600); |
|
+ log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600); |
|
if (log_ctx->ulogfd == -1) { |
|
retval = errno; |
|
goto cleanup; |
|
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c |
|
index 1da40b51d0..f3ab7340a6 100644 |
|
--- a/src/lib/krb5/ccache/cc_dir.c |
|
+++ b/src/lib/krb5/ccache/cc_dir.c |
|
@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents) |
|
char *newpath = NULL; |
|
FILE *fp = NULL; |
|
int fd = -1, status; |
|
+#ifdef USE_SELINUX |
|
+ void *selabel; |
|
+#endif |
|
|
|
if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0) |
|
return ENOMEM; |
|
+#ifdef USE_SELINUX |
|
+ selabel = krb5int_push_fscreatecon_for(primary_path); |
|
+#endif |
|
fd = mkstemp(newpath); |
|
+#ifdef USE_SELINUX |
|
+ krb5int_pop_fscreatecon(selabel); |
|
+#endif |
|
if (fd < 0) |
|
goto cleanup; |
|
#ifdef HAVE_CHMOD |
|
@@ -221,10 +230,23 @@ static krb5_error_code |
|
verify_dir(krb5_context context, const char *dirname) |
|
{ |
|
struct stat st; |
|
+ int status; |
|
+#ifdef USE_SELINUX |
|
+ void *selabel; |
|
+#endif |
|
|
|
if (stat(dirname, &st) < 0) { |
|
- if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0) |
|
- return 0; |
|
+ if (errno == ENOENT) { |
|
+#ifdef USE_SELINUX |
|
+ selabel = krb5int_push_fscreatecon_for(dirname); |
|
+#endif |
|
+ status = mkdir(dirname, S_IRWXU); |
|
+#ifdef USE_SELINUX |
|
+ krb5int_pop_fscreatecon(selabel); |
|
+#endif |
|
+ if (status == 0) |
|
+ return 0; |
|
+ } |
|
k5_setmsg(context, KRB5_FCC_NOFILE, |
|
_("Credential cache directory %s does not exist"), |
|
dirname); |
|
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c |
|
index e510211fc5..f3ea28c8ec 100644 |
|
--- a/src/lib/krb5/keytab/kt_file.c |
|
+++ b/src/lib/krb5/keytab/kt_file.c |
|
@@ -735,14 +735,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode) |
|
|
|
KTCHECKLOCK(id); |
|
errno = 0; |
|
- KTFILEP(id) = fopen(KTFILENAME(id), |
|
+ KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), |
|
(mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb"); |
|
if (!KTFILEP(id)) { |
|
if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) { |
|
/* try making it first time around */ |
|
k5_create_secure_file(context, KTFILENAME(id)); |
|
errno = 0; |
|
- KTFILEP(id) = fopen(KTFILENAME(id), "rb+"); |
|
+ KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+"); |
|
if (!KTFILEP(id)) |
|
goto report_errno; |
|
writevno = 1; |
|
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c |
|
index 4cbbbb270a..c4058ddc96 100644 |
|
--- a/src/lib/krb5/os/trace.c |
|
+++ b/src/lib/krb5/os/trace.c |
|
@@ -460,7 +460,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename) |
|
fd = malloc(sizeof(*fd)); |
|
if (fd == NULL) |
|
return ENOMEM; |
|
- *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600); |
|
+ *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600); |
|
if (*fd == -1) { |
|
free(fd); |
|
return errno; |
|
diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c |
|
index 9a506e9d44..f92ab47143 100644 |
|
--- a/src/plugins/kdb/db2/adb_openclose.c |
|
+++ b/src/plugins/kdb/db2/adb_openclose.c |
|
@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename, |
|
* needs be open read/write so that write locking can work with |
|
* POSIX systems |
|
*/ |
|
- if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) { |
|
+ if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) { |
|
/* |
|
* maybe someone took away write permission so we could only |
|
* get shared locks? |
|
diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c |
|
index 2c163d91cc..9a344a603e 100644 |
|
--- a/src/plugins/kdb/db2/kdb_db2.c |
|
+++ b/src/plugins/kdb/db2/kdb_db2.c |
|
@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc) |
|
if (retval) |
|
return retval; |
|
|
|
- dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC, |
|
- 0600); |
|
+ dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name, |
|
+ O_CREAT | O_RDWR | O_TRUNC, 0600); |
|
if (dbc->db_lf_file < 0) { |
|
retval = errno; |
|
goto cleanup; |
|
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c |
|
index 2977b17f3a..d5809a5a93 100644 |
|
--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c |
|
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c |
|
@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c 8.11 (Berkeley) 11/2/95"; |
|
#include <string.h> |
|
#include <unistd.h> |
|
|
|
+#include "k5-int.h" |
|
#include "db-int.h" |
|
#include "btree.h" |
|
|
|
@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags) |
|
goto einval; |
|
} |
|
|
|
- if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0) |
|
+ if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0) |
|
goto err; |
|
|
|
} else { |
|
diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c |
|
index 862dbb1640..686a960c96 100644 |
|
--- a/src/plugins/kdb/db2/libdb2/hash/hash.c |
|
+++ b/src/plugins/kdb/db2/libdb2/hash/hash.c |
|
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c 8.12 (Berkeley) 11/7/95"; |
|
#include <assert.h> |
|
#endif |
|
|
|
+#include "k5-int.h" |
|
#include "db-int.h" |
|
#include "hash.h" |
|
#include "page.h" |
|
@@ -129,7 +130,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags) |
|
new_table = 1; |
|
} |
|
if (file) { |
|
- if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1) |
|
+ if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1) |
|
RETURN_ERROR(errno, error0); |
|
(void)fcntl(hashp->fp, F_SETFD, 1); |
|
} |
|
diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c |
|
index d8b26e7011..b0daa7c021 100644 |
|
--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c |
|
+++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c |
|
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c 8.12 (Berkeley) 11/18/94"; |
|
#include <stdio.h> |
|
#include <unistd.h> |
|
|
|
+#include "k5-int.h" |
|
#include "db-int.h" |
|
#include "recno.h" |
|
|
|
@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags) |
|
int rfd = -1, sverrno; |
|
|
|
/* Open the user's file -- if this fails, we're done. */ |
|
- if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0) |
|
+ if (fname != NULL && |
|
+ (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0) |
|
return (NULL); |
|
|
|
if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) { |
|
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c |
|
index e87688d666..30f7c00ab5 100644 |
|
--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c |
|
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c |
|
@@ -190,7 +190,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv) |
|
|
|
/* set password in the file */ |
|
old_mode = umask(0177); |
|
- pfile = fopen(file_name, "a+"); |
|
+ pfile = WRITABLEFOPEN(file_name, "a+"); |
|
if (pfile == NULL) { |
|
com_err(me, errno, _("Failed to open file %s: %s"), file_name, |
|
strerror (errno)); |
|
@@ -231,6 +231,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv) |
|
* Delete the existing entry and add the new entry |
|
*/ |
|
FILE *newfile; |
|
+#ifdef USE_SELINUX |
|
+ void *selabel; |
|
+#endif |
|
|
|
mode_t omask; |
|
|
|
@@ -242,7 +245,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv) |
|
} |
|
|
|
omask = umask(077); |
|
+#ifdef USE_SELINUX |
|
+ selabel = krb5int_push_fscreatecon_for(file_name); |
|
+#endif |
|
newfile = fopen(tmp_file, "w"); |
|
+#ifdef USE_SELINUX |
|
+ krb5int_pop_fscreatecon(selabel); |
|
+#endif |
|
umask (omask); |
|
if (newfile == NULL) { |
|
com_err(me, errno, _("Error creating file %s"), tmp_file); |
|
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c |
|
index aa951df05f..79f9500f69 100644 |
|
--- a/src/util/profile/prof_file.c |
|
+++ b/src/util/profile/prof_file.c |
|
@@ -33,6 +33,7 @@ |
|
#endif |
|
|
|
#include "k5-platform.h" |
|
+#include "k5-label.h" |
|
|
|
struct global_shared_profile_data { |
|
/* This is the head of the global list of shared trees */ |
|
@@ -391,7 +392,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile, |
|
|
|
errno = 0; |
|
|
|
- f = fopen(new_file, "w"); |
|
+ f = WRITABLEFOPEN(new_file, "w"); |
|
if (!f) { |
|
retval = errno; |
|
if (retval == 0) |
|
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in |
|
index 86d5a950a6..1052d53a1e 100644 |
|
--- a/src/util/support/Makefile.in |
|
+++ b/src/util/support/Makefile.in |
|
@@ -74,6 +74,7 @@ IPC_SYMS= \ |
|
|
|
STLIBOBJS= \ |
|
threads.o \ |
|
+ selinux.o \ |
|
init-addrinfo.o \ |
|
plugins.o \ |
|
errors.o \ |
|
@@ -168,7 +169,7 @@ SRCS=\ |
|
|
|
SHLIB_EXPDEPS = |
|
# Add -lm if dumping thread stats, for sqrt. |
|
-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB) |
|
+SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB) |
|
|
|
DEPLIBS= |
|
|
|
diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c |
|
new file mode 100644 |
|
index 0000000000..807d039da3 |
|
--- /dev/null |
|
+++ b/src/util/support/selinux.c |
|
@@ -0,0 +1,405 @@ |
|
+/* |
|
+ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc. 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. |
|
+ * |
|
+ * Neither the name of Red Hat, Inc. nor the names of its contributors may be |
|
+ * used to endorse or promote products derived from this software without |
|
+ * specific prior written permission. |
|
+ * |
|
+ * 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 OWNER 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. |
|
+ * |
|
+ * File-opening wrappers for creating correctly-labeled files. So far, we can |
|
+ * assume that this is Linux-specific, so we make many simplifying assumptions. |
|
+ */ |
|
+ |
|
+#include "../../include/autoconf.h" |
|
+ |
|
+#ifdef USE_SELINUX |
|
+ |
|
+#include <k5-label.h> |
|
+#include <k5-platform.h> |
|
+ |
|
+#include <sys/types.h> |
|
+#include <sys/stat.h> |
|
+ |
|
+#include <errno.h> |
|
+#include <fcntl.h> |
|
+#include <limits.h> |
|
+#include <pthread.h> |
|
+#include <stdarg.h> |
|
+#include <stdio.h> |
|
+#include <stdlib.h> |
|
+#include <string.h> |
|
+#include <unistd.h> |
|
+ |
|
+#include <selinux/selinux.h> |
|
+#include <selinux/context.h> |
|
+#include <selinux/label.h> |
|
+ |
|
+/* #define DEBUG 1 */ |
|
+static void |
|
+debug_log(const char *fmt, ...) |
|
+{ |
|
+#ifdef DEBUG |
|
+ va_list ap; |
|
+ va_start(ap, fmt); |
|
+ if (isatty(fileno(stderr))) { |
|
+ vfprintf(stderr, fmt, ap); |
|
+ } |
|
+ va_end(ap); |
|
+#endif |
|
+ |
|
+ return; |
|
+} |
|
+ |
|
+/* Mutex used to serialize use of the process-global file creation context. */ |
|
+k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER; |
|
+ |
|
+/* Make sure we finish initializing that mutex before attempting to use it. */ |
|
+k5_once_t labeled_once = K5_ONCE_INIT; |
|
+static void |
|
+label_mutex_init(void) |
|
+{ |
|
+ k5_mutex_finish_init(&labeled_mutex); |
|
+} |
|
+ |
|
+static struct selabel_handle *selabel_ctx; |
|
+static time_t selabel_last_changed; |
|
+ |
|
+MAKE_FINI_FUNCTION(cleanup_fscreatecon); |
|
+ |
|
+static void |
|
+cleanup_fscreatecon(void) |
|
+{ |
|
+ if (selabel_ctx != NULL) { |
|
+ selabel_close(selabel_ctx); |
|
+ selabel_ctx = NULL; |
|
+ } |
|
+} |
|
+ |
|
+static char * |
|
+push_fscreatecon(const char *pathname, mode_t mode) |
|
+{ |
|
+ char *previous, *configuredsc, *currentsc, *genpath; |
|
+ const char *derivedsc, *fullpath, *currentuser; |
|
+ context_t current, derived; |
|
+ |
|
+ previous = configuredsc = currentsc = genpath = NULL; |
|
+ derivedsc = NULL; |
|
+ current = derived = NULL; |
|
+ |
|
+ fullpath = pathname; |
|
+ |
|
+ if (!is_selinux_enabled()) { |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ if (getfscreatecon(&previous) != 0) { |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ /* Canonicalize pathname */ |
|
+ if (pathname[0] != '/') { |
|
+ char *wd; |
|
+ size_t len; |
|
+ len = 0; |
|
+ |
|
+ wd = getcwd(NULL, len); |
|
+ if (wd == NULL) { |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ len = strlen(wd) + 1 + strlen(pathname) + 1; |
|
+ genpath = malloc(len); |
|
+ if (genpath == NULL) { |
|
+ free(wd); |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ sprintf(genpath, "%s/%s", wd, pathname); |
|
+ free(wd); |
|
+ fullpath = genpath; |
|
+ } |
|
+ |
|
+ debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode); |
|
+ |
|
+ /* Check whether context file has changed under us */ |
|
+ if (selabel_ctx != NULL || selabel_last_changed == 0) { |
|
+ const char *cpath; |
|
+ struct stat st; |
|
+ int i = -1; |
|
+ |
|
+ cpath = selinux_file_context_path(); |
|
+ if (cpath == NULL || (i = stat(cpath, &st)) != 0 || |
|
+ st.st_mtime != selabel_last_changed) { |
|
+ cleanup_fscreatecon(); |
|
+ |
|
+ selabel_last_changed = i ? time(NULL) : st.st_mtime; |
|
+ } |
|
+ } |
|
+ |
|
+ if (selabel_ctx == NULL) { |
|
+ selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0); |
|
+ } |
|
+ |
|
+ if (selabel_ctx != NULL && |
|
+ selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) { |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ if (genpath != NULL) { |
|
+ free(genpath); |
|
+ genpath = NULL; |
|
+ } |
|
+ |
|
+ if (configuredsc == NULL) { |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ getcon(¤tsc); |
|
+ |
|
+ /* AAAAAAAA */ |
|
+ if (currentsc != NULL) { |
|
+ derived = context_new(configuredsc); |
|
+ |
|
+ if (derived != NULL) { |
|
+ current = context_new(currentsc); |
|
+ |
|
+ if (current != NULL) { |
|
+ currentuser = context_user_get(current); |
|
+ |
|
+ if (currentuser != NULL) { |
|
+ if (context_user_set(derived, |
|
+ currentuser) == 0) { |
|
+ derivedsc = context_str(derived); |
|
+ |
|
+ if (derivedsc != NULL) { |
|
+ freecon(configuredsc); |
|
+ configuredsc = strdup(derivedsc); |
|
+ } |
|
+ } |
|
+ } |
|
+ |
|
+ context_free(current); |
|
+ } |
|
+ |
|
+ context_free(derived); |
|
+ } |
|
+ |
|
+ freecon(currentsc); |
|
+ } |
|
+ |
|
+ debug_log("Setting file creation context to \"%s\".\n", configuredsc); |
|
+ if (setfscreatecon(configuredsc) != 0) { |
|
+ debug_log("Unable to determine current context.\n"); |
|
+ goto fail; |
|
+ } |
|
+ |
|
+ freecon(configuredsc); |
|
+ return previous; |
|
+ |
|
+fail: |
|
+ if (previous != NULL) { |
|
+ freecon(previous); |
|
+ } |
|
+ if (genpath != NULL) { |
|
+ free(genpath); |
|
+ } |
|
+ if (configuredsc != NULL) { |
|
+ freecon(configuredsc); |
|
+ } |
|
+ |
|
+ cleanup_fscreatecon(); |
|
+ return NULL; |
|
+} |
|
+ |
|
+static void |
|
+pop_fscreatecon(char *previous) |
|
+{ |
|
+ if (!is_selinux_enabled()) { |
|
+ return; |
|
+ } |
|
+ |
|
+ if (previous != NULL) { |
|
+ debug_log("Resetting file creation context to \"%s\".\n", previous); |
|
+ } else { |
|
+ debug_log("Resetting file creation context to default.\n"); |
|
+ } |
|
+ |
|
+ /* NULL resets to default */ |
|
+ setfscreatecon(previous); |
|
+ |
|
+ if (previous != NULL) { |
|
+ freecon(previous); |
|
+ } |
|
+ |
|
+ /* Need to clean this up here otherwise it leaks */ |
|
+ cleanup_fscreatecon(); |
|
+} |
|
+ |
|
+void * |
|
+krb5int_push_fscreatecon_for(const char *pathname) |
|
+{ |
|
+ struct stat st; |
|
+ void *retval; |
|
+ |
|
+ k5_once(&labeled_once, label_mutex_init); |
|
+ k5_mutex_lock(&labeled_mutex); |
|
+ |
|
+ if (stat(pathname, &st) != 0) { |
|
+ st.st_mode = S_IRUSR | S_IWUSR; |
|
+ } |
|
+ |
|
+ retval = push_fscreatecon(pathname, st.st_mode); |
|
+ return retval ? retval : (void *) -1; |
|
+} |
|
+ |
|
+void |
|
+krb5int_pop_fscreatecon(void *con) |
|
+{ |
|
+ if (con != NULL) { |
|
+ pop_fscreatecon((con == (void *) -1) ? NULL : con); |
|
+ k5_mutex_unlock(&labeled_mutex); |
|
+ } |
|
+} |
|
+ |
|
+FILE * |
|
+krb5int_labeled_fopen(const char *path, const char *mode) |
|
+{ |
|
+ FILE *fp; |
|
+ int errno_save; |
|
+ char *ctx; |
|
+ |
|
+ if ((strcmp(mode, "r") == 0) || |
|
+ (strcmp(mode, "rb") == 0)) { |
|
+ return fopen(path, mode); |
|
+ } |
|
+ |
|
+ k5_once(&labeled_once, label_mutex_init); |
|
+ k5_mutex_lock(&labeled_mutex); |
|
+ ctx = push_fscreatecon(path, 0); |
|
+ |
|
+ fp = fopen(path, mode); |
|
+ errno_save = errno; |
|
+ |
|
+ pop_fscreatecon(ctx); |
|
+ k5_mutex_unlock(&labeled_mutex); |
|
+ |
|
+ errno = errno_save; |
|
+ return fp; |
|
+} |
|
+ |
|
+int |
|
+krb5int_labeled_creat(const char *path, mode_t mode) |
|
+{ |
|
+ int fd; |
|
+ int errno_save; |
|
+ char *ctx; |
|
+ |
|
+ k5_once(&labeled_once, label_mutex_init); |
|
+ k5_mutex_lock(&labeled_mutex); |
|
+ ctx = push_fscreatecon(path, 0); |
|
+ |
|
+ fd = creat(path, mode); |
|
+ errno_save = errno; |
|
+ |
|
+ pop_fscreatecon(ctx); |
|
+ k5_mutex_unlock(&labeled_mutex); |
|
+ |
|
+ errno = errno_save; |
|
+ return fd; |
|
+} |
|
+ |
|
+int |
|
+krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev) |
|
+{ |
|
+ int ret; |
|
+ int errno_save; |
|
+ char *ctx; |
|
+ |
|
+ k5_once(&labeled_once, label_mutex_init); |
|
+ k5_mutex_lock(&labeled_mutex); |
|
+ ctx = push_fscreatecon(path, mode); |
|
+ |
|
+ ret = mknod(path, mode, dev); |
|
+ errno_save = errno; |
|
+ |
|
+ pop_fscreatecon(ctx); |
|
+ k5_mutex_unlock(&labeled_mutex); |
|
+ |
|
+ errno = errno_save; |
|
+ return ret; |
|
+} |
|
+ |
|
+int |
|
+krb5int_labeled_mkdir(const char *path, mode_t mode) |
|
+{ |
|
+ int ret; |
|
+ int errno_save; |
|
+ char *ctx; |
|
+ |
|
+ k5_once(&labeled_once, label_mutex_init); |
|
+ k5_mutex_lock(&labeled_mutex); |
|
+ ctx = push_fscreatecon(path, S_IFDIR); |
|
+ |
|
+ ret = mkdir(path, mode); |
|
+ errno_save = errno; |
|
+ |
|
+ pop_fscreatecon(ctx); |
|
+ k5_mutex_unlock(&labeled_mutex); |
|
+ |
|
+ errno = errno_save; |
|
+ return ret; |
|
+} |
|
+ |
|
+int |
|
+krb5int_labeled_open(const char *path, int flags, ...) |
|
+{ |
|
+ int fd; |
|
+ int errno_save; |
|
+ char *ctx; |
|
+ mode_t mode; |
|
+ va_list ap; |
|
+ |
|
+ if ((flags & O_CREAT) == 0) { |
|
+ return open(path, flags); |
|
+ } |
|
+ |
|
+ k5_once(&labeled_once, label_mutex_init); |
|
+ k5_mutex_lock(&labeled_mutex); |
|
+ ctx = push_fscreatecon(path, 0); |
|
+ |
|
+ va_start(ap, flags); |
|
+ mode = va_arg(ap, mode_t); |
|
+ fd = open(path, flags, mode); |
|
+ va_end(ap); |
|
+ |
|
+ errno_save = errno; |
|
+ |
|
+ pop_fscreatecon(ctx); |
|
+ k5_mutex_unlock(&labeled_mutex); |
|
+ |
|
+ errno = errno_save; |
|
+ return fd; |
|
+} |
|
+ |
|
+#endif /* USE_SELINUX */ |
|
-- |
|
2.41.0 |
|
|
|
|