[Open-scap] [PATCH] [probes] add selinuxsecuritycontext probe
Petr Lautrbach
plautrba at redhat.com
Fri Jul 29 10:36:50 UTC 2011
---
notes:
it doesn't work with running mcstrans daemon right now - raw sensitivities
and categories are not recognized
mitre test fails on 2 issues:
* /etc/mtab is symlink in fedora 15 and it seems to be somehow ignored by
oval_fts_open() and oval_fts_read():
[I:probes/oval_fts.c:443:oval_fts_read] Only the target of a symlink gets reported; ignored.
* path element "/etc/profile.d/" from object definition is transformed to
"/etc/profile.d" in item
configure.ac | 5 +-
src/OVAL/oval_probe.c | 2 +
src/OVAL/oval_probe_ext.c | 1 +
src/OVAL/oval_probe_session.c | 1 +
src/OVAL/probes/Makefile.am | 7 +-
.../probes/unix/linux/selinuxsecuritycontext.c | 322 ++++++++++++++++++++
6 files changed, 335 insertions(+), 3 deletions(-)
create mode 100644 src/OVAL/probes/unix/linux/selinuxsecuritycontext.c
diff --git a/configure.ac b/configure.ac
index c85a851..97610b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -347,7 +347,7 @@ AC_CHECK_LIB(
[selinux_cflags=`pkg-config libselinux --cflags`
selinux_libs=`pkg-config libselinux --libs`
have_selinux=yes
- AC_DEFINE([ENABLE_PROBE_SELINUXBOOLEAN], [1], [Define if SELinux is available])
+ AC_DEFINE([ENABLE_PROBES_SELINUX], [1], [Define if SELinux is available])
]
)
@@ -729,7 +729,7 @@ AM_CONDITIONAL([WANT_BINDINGS], test "$bindings" = yes)
AM_CONDITIONAL([ENABLE_VALGRIND_TESTS], test "$vgcheck" = yes)
AM_CONDITIONAL([HAVE_ODBX], test "$have_odbx" = yes)
AM_CONDITIONAL([ENABLE_PROBE_LDAP57], test "$probe_independent_ldap57" = yes)
-AM_CONDITIONAL(ENABLE_PROBE_SELINUXBOOLEAN, [test "$have_selinux" = "yes"])
+AM_CONDITIONAL(ENABLE_PROBES_SELINUX, [test "$have_selinux" = "yes"])
AC_CONFIG_FILES([Makefile
lib/Makefile
@@ -834,6 +834,7 @@ echo " rpminfo probe: $have_librpm"
echo " rpmverify probe: $have_librpm"
echo " partition probe: $probes_linux"
echo " selinuxboolean probe: $have_selinux"
+echo " selinuxsecuritycontext probe: $have_selinux"
echo ""
echo " === solaris probes ==="
diff --git a/src/OVAL/oval_probe.c b/src/OVAL/oval_probe.c
index 784f2ec..45a3308 100644
--- a/src/OVAL/oval_probe.c
+++ b/src/OVAL/oval_probe.c
@@ -68,6 +68,7 @@ oval_subtypedsc_t __s2n_tbl[] = {
/* 9005 */ {OVAL_LINUX_PARTITION, "partition", },
/* 9007 */ {OVAL_LINUX_RPMVERIFY, "rpmverify" },
/* 9008 */ {OVAL_LINUX_SELINUXBOOLEAN, "selinuxboolean" },
+ /* 9009 */ {OVAL_LINUX_SELINUXSECURITYCONTEXT, "selinuxsecuritycontext" },
/* 12001 */ {OVAL_SOLARIS_ISAINFO, "isainfo" },
/* 13001 */ {OVAL_UNIX_FILE, "file" },
/* 13003 */ {OVAL_UNIX_INTERFACE, "interface" },
@@ -107,6 +108,7 @@ oval_subtypedsc_t __n2s_tbl[] = {
/* 9007 */ {OVAL_LINUX_RPMVERIFY, "rpmverify" },
/* 13006 */ {OVAL_UNIX_RUNLEVEL, "runlevel" },
/* 9008 */ {OVAL_LINUX_SELINUXBOOLEAN, "selinuxboolean" },
+ /* 9009 */ {OVAL_LINUX_SELINUXSECURITYCONTEXT, "selinuxsecuritycontext" },
/* 13008 */ {OVAL_UNIX_SHADOW, "shadow" },
/* 7005 */ {OVAL_INDEPENDENT_SQL, "sql" },
/* 7013 */ {OVAL_INDEPENDENT_SQL57, "sql57" },
diff --git a/src/OVAL/oval_probe_ext.c b/src/OVAL/oval_probe_ext.c
index 12b0254..ceb8ee8 100644
--- a/src/OVAL/oval_probe_ext.c
+++ b/src/OVAL/oval_probe_ext.c
@@ -70,6 +70,7 @@ const oval_pdsc_t OSCAP_GSYM(default_pdsc)[] = {
{OVAL_LINUX_RPMVERIFY, "rpmverify", "probe_rpmverify"},
{OVAL_LINUX_PARTITION, "partition", "probe_partition"},
{OVAL_LINUX_SELINUXBOOLEAN, "selinuxboolean", "probe_selinuxboolean"},
+ {OVAL_LINUX_SELINUXSECURITYCONTEXT, "selinuxsecuritycontext", "probe_selinuxsecuritycontext"},
{OVAL_SOLARIS_ISAINFO, "isainfo", "probe_isainfo"},
{OVAL_UNIX_FILE, "file", "probe_file"},
{OVAL_UNIX_INTERFACE, "interface", "probe_interface"},
diff --git a/src/OVAL/oval_probe_session.c b/src/OVAL/oval_probe_session.c
index c478c65..fb7f142 100644
--- a/src/OVAL/oval_probe_session.c
+++ b/src/OVAL/oval_probe_session.c
@@ -130,6 +130,7 @@ oval_probe_session_t *oval_probe_session_new(struct oval_syschar_model *model)
oval_probe_handler_set(sess->ph, OVAL_LINUX_RPMVERIFY, oval_probe_ext_handler, sess->pext);
oval_probe_handler_set(sess->ph, OVAL_LINUX_PARTITION, oval_probe_ext_handler, sess->pext);
oval_probe_handler_set(sess->ph, OVAL_LINUX_SELINUXBOOLEAN, oval_probe_ext_handler, sess->pext);
+ oval_probe_handler_set(sess->ph, OVAL_LINUX_SELINUXSECURITYCONTEXT, oval_probe_ext_handler, sess->pext);
oval_probe_handler_set(sess->ph, OVAL_SOLARIS_ISAINFO, oval_probe_ext_handler, sess->pext);
oval_probe_handler_set(sess->ph, OVAL_UNIX_FILE, oval_probe_ext_handler, sess->pext);
oval_probe_handler_set(sess->ph, OVAL_UNIX_INTERFACE, oval_probe_ext_handler, sess->pext);
diff --git a/src/OVAL/probes/Makefile.am b/src/OVAL/probes/Makefile.am
index 2b3912f..00d99e6 100644
--- a/src/OVAL/probes/Makefile.am
+++ b/src/OVAL/probes/Makefile.am
@@ -160,11 +160,16 @@ probe_inetlisteningservers_SOURCES= unix/linux/inetlisteningservers.c
probe_inetlisteningservers_CFLAGS=
probe_inetlisteningservers_LDFLAGS=
-if ENABLE_PROBE_SELINUXBOOLEAN
+if ENABLE_PROBES_SELINUX
pkglibexec_PROGRAMS += probe_selinuxboolean
probe_selinuxboolean_SOURCES= unix/linux/selinuxboolean.c
probe_selinuxboolean_CFLAGS= @selinux_cflags@
probe_selinuxboolean_LDFLAGS= @selinux_libs@
+
+pkglibexec_PROGRAMS += probe_selinuxsecuritycontext
+probe_selinuxsecuritycontext_SOURCES= unix/linux/selinuxsecuritycontext.c
+probe_selinuxsecuritycontext_CFLAGS= @selinux_cflags@
+probe_selinuxsecuritycontext_LDFLAGS= @selinux_libs@
endif
if ENABLE_PROBE_RPMINFO
diff --git a/src/OVAL/probes/unix/linux/selinuxsecuritycontext.c b/src/OVAL/probes/unix/linux/selinuxsecuritycontext.c
new file mode 100644
index 0000000..16b176b
--- /dev/null
+++ b/src/OVAL/probes/unix/linux/selinuxsecuritycontext.c
@@ -0,0 +1,322 @@
+/**
+ * @file selinuxsecuritycontext.c
+ * @brief selinuxsecuritycontext probe
+ * @author "Petr Lautrbach" <plautrba at redhat.com>
+ *
+ * 2011/07/01 plautrba at redhat.com
+ * This probe is able to process a selinuxsecuritycontext_object as defined in OVAL 5.9
+ *
+ */
+
+/*
+ * Copyright 2011 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * "Petr Lautrbach" <plautrba at redhat.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <seap.h>
+#include <probe-api.h>
+#include <probe/entcmp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+
+#include "oval_fts.h"
+#include "util.h"
+
+#define FILE_SEPARATOR '/'
+
+static void split_level(const char *level, char **sensitivity, char **category) {
+ char *level_split;
+
+ level_split = strchr(level, ':');
+ if (level_split == NULL) {
+ *sensitivity = strdup(level);
+ *category = NULL;
+ }
+ else {
+ *sensitivity = strndup(level, level_split - level);
+ *category = strdup(level_split + 1);
+ }
+}
+
+/* parse range according to
+ * http://selinuxproject.org/page/NB_MLS#MLS_.2F_MCS_Range_Format
+*/
+static void split_range(const char *range, char **l_s, char **l_c, char **h_s, char **h_c) {
+ char *level;
+ const char *range_split;
+
+ range_split = strchr(range, '-');
+ if (range_split == NULL) {
+ /* there is only 1 level */
+ split_level(range, l_s, l_c);
+ *h_s = NULL;
+ *h_c = NULL;
+ }
+ else {
+ /* low level */
+ level = strndup(range, range_split - range);
+ split_level(level, l_s, l_c);
+ free(level);
+
+ /* high level */
+ level = strdup(range_split + 1);
+ split_level(level, h_s, h_c);
+ free(level);
+ }
+}
+
+static int selinuxsecuritycontext_process_cb (SEXP_t *pid_ent, probe_ctx *ctx) {
+
+ SEXP_t *pid_sexp, *item;
+ security_context_t pid_context;
+ context_t context;
+ int pid_number;
+ DIR *proc;
+ struct dirent *dir_entry;
+ const char *user, *role, *type, *range;
+ char *l_sensitivity, *l_category, *h_sensitivity, *h_category;
+
+ if ((proc = opendir("/proc")) == NULL) {
+ dE("Can't open /proc dir: %s\n", strerror(errno));
+
+ probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_ERROR);
+ return errno;
+ }
+
+ while ((dir_entry = readdir(proc))) {
+ if (strspn(dir_entry->d_name, "0123456789") != strlen(dir_entry->d_name))
+ continue;
+
+ pid_number = atoi(dir_entry->d_name);
+ pid_sexp = SEXP_number_newi_32(pid_number);
+ if (probe_entobj_cmp(pid_ent, pid_sexp) == OVAL_RESULT_TRUE) {
+
+ if (getpidcon(pid_number, &pid_context) == -1) {
+ /* error getting pid selinux context */
+ dW("Can't get selinux context for process %d\n", pid_number);
+ SEXP_free(pid_sexp);
+ continue;
+ }
+
+ context = context_new(pid_context);
+
+ user = context_user_get(context);
+ role = context_role_get(context);
+ type = context_type_get(context);
+ range = context_range_get(context);
+
+ split_range(range, &l_sensitivity, &l_category, &h_sensitivity, &h_category);
+ item = probe_item_create(OVAL_LINUX_SELINUXSECURITYCONTEXT, NULL,
+ "pid", OVAL_DATATYPE_INTEGER, pid_number,
+ "user", OVAL_DATATYPE_STRING, user,
+ "role", OVAL_DATATYPE_STRING, role,
+ "type", OVAL_DATATYPE_STRING, type,
+ "low_sensitivity", OVAL_DATATYPE_STRING, l_sensitivity,
+ "low_category", OVAL_DATATYPE_STRING, l_category,
+ "high_sensitivity", OVAL_DATATYPE_STRING, h_sensitivity,
+ "high_category", OVAL_DATATYPE_STRING, h_category,
+
+ NULL);
+ probe_item_collect(ctx, item);
+
+ context_free(context);
+ freecon(pid_context);
+ }
+ SEXP_free(pid_sexp);
+ }
+ closedir(proc);
+
+ return 0;
+}
+
+
+static int selinuxsecuritycontext_file_cb (const char *p, const char *f, probe_ctx *ctx)
+{
+ SEXP_t *item;
+
+ char pbuf[PATH_MAX+1];
+ size_t plen, flen;
+
+ security_context_t file_context;
+ int file_context_size;
+ context_t context;
+ const char *user, *role, *type, *range;
+ char *l_sensitivity, *l_category, *h_sensitivity, *h_category;
+ int err = 0;
+
+ /* directory */
+ if (f == NULL)
+ flen = 0;
+ else
+ flen = strlen (f);
+
+ /*
+ * Prepare path
+ */
+ plen = strlen (p);
+
+ if (plen + flen + 1 > PATH_MAX)
+ return (-1);
+
+ memcpy (pbuf, p, sizeof (char) * plen);
+
+ if (p[plen - 1] != FILE_SEPARATOR) {
+ pbuf[plen] = FILE_SEPARATOR;
+ ++plen;
+ }
+
+ if (f != NULL)
+ memcpy (pbuf + plen, f, sizeof (char) * flen);
+
+ pbuf[plen+flen] = '\0';
+
+ file_context_size = getfilecon(pbuf, &file_context);
+ if (file_context_size == -1) {
+ SEXP_t *at, *r0, *r1;
+ dE("Can't get context for %s: %s\n", pbuf, strerror(errno));
+ strerror_r (errno, pbuf, PATH_MAX);
+ pbuf[PATH_MAX] = '\0';
+
+ at = probe_attr_creat ("status", r0 = SEXP_number_newi_32 (OVAL_STATUS_ERROR),
+ "message", r1 = SEXP_string_newf ("%s", pbuf),
+ NULL);
+
+ SEXP_vfree (r0, r1, NULL);
+
+ item = probe_item_creat ("selinuxsecuritycontext_item", at, NULL);
+ SEXP_free(at);
+ err = errno;
+
+ }
+ else {
+ context = context_new(file_context);
+
+ user = context_user_get(context);
+ role = context_role_get(context);
+ type = context_type_get(context);
+ range = context_range_get(context);
+
+ split_range(range, &l_sensitivity, &l_category, &h_sensitivity, &h_category);
+
+ item = probe_item_create(OVAL_LINUX_SELINUXSECURITYCONTEXT, NULL,
+ "filepath", OVAL_DATATYPE_STRING, pbuf,
+ "path", OVAL_DATATYPE_STRING, p,
+ "filename", OVAL_DATATYPE_STRING, f,
+ "user", OVAL_DATATYPE_STRING, user,
+ "role", OVAL_DATATYPE_STRING, role,
+ "type", OVAL_DATATYPE_STRING, type,
+ "low_sensitivity", OVAL_DATATYPE_STRING, l_sensitivity,
+ "low_category", OVAL_DATATYPE_STRING, l_category,
+ "high_sensitivity", OVAL_DATATYPE_STRING, h_sensitivity,
+ "high_category", OVAL_DATATYPE_STRING, h_category,
+ "rawlow_sensitivity", OVAL_DATATYPE_STRING, l_sensitivity,
+ "rawlow_category", OVAL_DATATYPE_STRING, l_category,
+ "rawhigh_sensitivity", OVAL_DATATYPE_STRING, h_sensitivity,
+ "rawhigh_category", OVAL_DATATYPE_STRING, h_category,
+ NULL);
+ context_free(context);
+ freecon(file_context);
+ }
+ probe_item_collect(ctx, item);
+
+ return (err);
+}
+
+int probe_main(probe_ctx *ctx, void *arg)
+{
+ SEXP_t *probe_in;
+ SEXP_t *path, *filename, *filepath, *pid, *behaviors = NULL;
+ int process_pid;
+
+ OVAL_FTS *ofts;
+ OVAL_FTSENT *ofts_ent;
+
+ if ( ! is_selinux_enabled()) {
+ probe_cobj_set_flag(probe_ctx_getresult(ctx), SYSCHAR_FLAG_NOT_APPLICABLE);
+ return 0;
+ }
+
+ probe_in = probe_ctx_getobject(ctx);
+
+ path = probe_obj_getent (probe_in, "path", 1);
+ filename = probe_obj_getent (probe_in, "filename", 1);
+ filepath = probe_obj_getent (probe_in, "filepath", 1);
+ pid = probe_obj_getent (probe_in, "pid", 1);
+
+ if (((path == NULL || filename == NULL) && filepath==NULL ) && pid == NULL) {
+ SEXP_free (path);
+ SEXP_free (filename);
+ SEXP_free (filepath);
+ SEXP_free (pid);
+
+ return (PROBE_ENOELM);
+ }
+
+ if (filepath || (path && filename)) {
+ probe_filebehaviors_canonicalize(&behaviors);
+
+ if ((ofts = oval_fts_open(path, filename, filepath, behaviors)) != NULL) {
+ while ((ofts_ent = oval_fts_read(ofts)) != NULL) {
+ selinuxsecuritycontext_file_cb(ofts_ent->path, ofts_ent->file, ctx);
+ oval_ftsent_free(ofts_ent);
+ }
+
+ oval_fts_close(ofts);
+ }
+ SEXP_free(behaviors);
+ }
+
+ if (pid != NULL) {
+ PROBE_ENT_I32VAL(pid, process_pid, return -1;);
+
+ if (process_pid == 0) {
+ SEXP_t *nref, *nval, *pid2;
+
+ nref = SEXP_list_first(probe_in);
+ nval = SEXP_number_newu_32(getpid());
+ pid2 = SEXP_list_new(nref, nval, NULL);
+ SEXP_vfree(pid, nref, nval, NULL);
+ pid = pid2;
+ }
+
+ selinuxsecuritycontext_process_cb(pid, ctx);
+ }
+
+ SEXP_free (path);
+ SEXP_free (filename);
+ SEXP_free (filepath);
+ SEXP_free (pid);
+
+ return 0;
+}
--
1.7.6
More information about the Open-scap-list
mailing list