diff options
Diffstat (limited to 'libselinux/utils')
-rw-r--r-- | libselinux/utils/Makefile | 32 | ||||
-rw-r--r-- | libselinux/utils/avcstat.c | 234 | ||||
-rw-r--r-- | libselinux/utils/compute_av.c | 55 | ||||
-rw-r--r-- | libselinux/utils/compute_create.c | 36 | ||||
-rw-r--r-- | libselinux/utils/compute_member.c | 36 | ||||
-rw-r--r-- | libselinux/utils/compute_relabel.c | 36 | ||||
-rw-r--r-- | libselinux/utils/compute_user.c | 38 | ||||
-rw-r--r-- | libselinux/utils/getconlist.c | 73 | ||||
-rw-r--r-- | libselinux/utils/getdefaultcon.c | 80 | ||||
-rw-r--r-- | libselinux/utils/getenforce.c | 31 | ||||
-rw-r--r-- | libselinux/utils/getfilecon.c | 27 | ||||
-rw-r--r-- | libselinux/utils/getpidcon.c | 31 | ||||
-rw-r--r-- | libselinux/utils/getsebool.c | 105 | ||||
-rw-r--r-- | libselinux/utils/getseuser.c | 40 | ||||
-rw-r--r-- | libselinux/utils/matchpathcon.c | 143 | ||||
-rw-r--r-- | libselinux/utils/policyvers.c | 18 | ||||
-rw-r--r-- | libselinux/utils/selinux_check_securetty_context.c | 35 | ||||
-rw-r--r-- | libselinux/utils/selinuxenabled.c | 9 | ||||
-rw-r--r-- | libselinux/utils/setenforce.c | 42 | ||||
-rw-r--r-- | libselinux/utils/setfilecon.c | 24 | ||||
-rw-r--r-- | libselinux/utils/togglesebool.c | 97 |
21 files changed, 1222 insertions, 0 deletions
diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile new file mode 100644 index 00000000..a2c0a53b --- /dev/null +++ b/libselinux/utils/Makefile @@ -0,0 +1,32 @@ +# Installation directories. +PREFIX ?= $(DESTDIR)/usr +LIBDIR ?= $(PREFIX)/lib +BINDIR ?= $(PREFIX)/sbin + +CFLAGS ?= -Wall +override CFLAGS += -I../include -D_GNU_SOURCE $(EMFLAGS) +LDLIBS += -L../src -lselinux -L$(LIBDIR) + +TARGETS=$(patsubst %.c,%,$(wildcard *.c)) +ifeq ($(DISABLE_AVC),y) + UNUSED_TARGETS+=compute_av compute_create compute_member compute_relabel +endif +ifeq ($(DISABLE_BOOL),y) + UNUSED_TARGETS+=getsebool togglesebool +endif +TARGETS:= $(filter-out $(UNUSED_TARGETS), $(TARGETS)) + +all: $(TARGETS) + +install: all + -mkdir -p $(BINDIR) + install -m 755 $(TARGETS) $(BINDIR) + +clean: + rm -f $(TARGETS) *.o + +indent: + ../../scripts/Lindent $(wildcard *.[ch]) + +relabel: + diff --git a/libselinux/utils/avcstat.c b/libselinux/utils/avcstat.c new file mode 100644 index 00000000..772118a1 --- /dev/null +++ b/libselinux/utils/avcstat.c @@ -0,0 +1,234 @@ +/* + * avcstat - Display SELinux avc statistics. + * + * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <libgen.h> +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/limits.h> + +#define DEF_STAT_FILE "/avc/cache_stats" +#define DEF_BUF_SIZE 8192 +#define HEADERS "lookups hits misses allocations reclaims frees" + +struct avc_cache_stats { + unsigned long long lookups; + unsigned long long hits; + unsigned long long misses; + unsigned long long allocations; + unsigned long long reclaims; + unsigned long long frees; +}; + +static int interval; +static int rows; +static char *progname; +static char buf[DEF_BUF_SIZE]; + +/* selinuxfs mount point */ +extern char *selinux_mnt; + +static void die(const char *msg, ...) +{ + va_list args; + + fputs("ERROR: ", stderr); + + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + + if (errno) + fprintf(stderr, ": %s", strerror(errno)); + + fputc('\n', stderr); + exit(1); +} + +static void usage(void) +{ + printf("\nUsage: %s [-c] [-f status_file] [interval]\n\n", progname); + printf + ("Display SELinux AVC statistics. If the interval parameter is specified, the\n"); + printf + ("program will loop, displaying updated statistics every \'interval\' seconds.\n"); + printf + ("Relative values are displayed by default. Use the -c option to specify the\n"); + printf + ("display of cumulative values. The -f option specifies the location of the\n"); + printf("AVC statistics file, defaulting to \'%s%s\'.\n\n", selinux_mnt, + DEF_STAT_FILE); +} + +static void set_window_rows(void) +{ + int ret; + struct winsize ws; + + ret = ioctl(fileno(stdout), TIOCGWINSZ, &ws); + if (ret < 0 || ws.ws_row < 3) + ws.ws_row = 24; + rows = ws.ws_row; +} + +static void sighandler(int num) +{ + if (num == SIGWINCH) + set_window_rows(); +} + +int main(int argc, char **argv) +{ + struct avc_cache_stats tot, rel, last; + int fd, i, cumulative = 0; + struct sigaction sa; + char avcstatfile[PATH_MAX]; + snprintf(avcstatfile, sizeof avcstatfile, "%s%s", selinux_mnt, + DEF_STAT_FILE); + progname = basename(argv[0]); + + memset(&last, 0, sizeof(last)); + + while ((i = getopt(argc, argv, "cf:h?-")) != -1) { + switch (i) { + case 'c': + cumulative = 1; + break; + case 'f': + strncpy(avcstatfile, optarg, sizeof avcstatfile); + break; + case 'h': + case '-': + usage(); + exit(0); + default: + usage(); + die("unrecognized parameter", i); + } + } + + if (optind < argc) { + char *arg = argv[optind]; + unsigned int n = strtoul(arg, NULL, 10); + + if (errno == ERANGE) { + usage(); + die("invalid interval \'%s\'", arg); + } + if (n == 0) { + usage(); + exit(0); + } + interval = n; + } + + sa.sa_handler = sighandler; + sa.sa_flags = SA_RESTART; + + i = sigaction(SIGWINCH, &sa, NULL); + if (i < 0) + die("sigaction"); + + set_window_rows(); + fd = open(avcstatfile, O_RDONLY); + if (fd < 0) + die("open: \'%s\'", avcstatfile); + + for (i = 0;; i++) { + char *line; + ssize_t ret, parsed = 0; + + memset(buf, 0, DEF_BUF_SIZE); + ret = read(fd, buf, DEF_BUF_SIZE); + if (ret < 0) + die("read"); + + if (ret == 0) + die("read: \'%s\': unexpected end of file", + avcstatfile); + + line = strtok(buf, "\n"); + if (!line) + die("unable to parse \'%s\': end of line not found", + avcstatfile); + + if (strcmp(line, HEADERS)) + die("unable to parse \'%s\': invalid headers", + avcstatfile); + + if (!i || !(i % (rows - 2))) + printf("%10s %10s %10s %10s %10s %10s\n", "lookups", + "hits", "misses", "allocs", "reclaims", "frees"); + + memset(&tot, 0, sizeof(tot)); + + while ((line = strtok(NULL, "\n"))) { + struct avc_cache_stats tmp; + + ret = sscanf(line, "%llu %llu %llu %llu %llu %llu", + &tmp.lookups, + &tmp.hits, + &tmp.misses, + &tmp.allocations, + &tmp.reclaims, &tmp.frees); + if (ret != 6) + die("unable to parse \'%s\': scan error", + avcstatfile); + + tot.lookups += tmp.lookups; + tot.hits += tmp.hits; + tot.misses += tmp.misses; + tot.allocations += tmp.allocations; + tot.reclaims += tmp.reclaims; + tot.frees += tmp.frees; + parsed = 1; + } + + if (!parsed) + die("unable to parse \'%s\': no data", avcstatfile); + + if (cumulative || (!cumulative && !i)) + printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n", + tot.lookups, tot.hits, tot.misses, + tot.allocations, tot.reclaims, tot.frees); + else { + rel.lookups = tot.lookups - last.lookups; + rel.hits = tot.hits - last.hits; + rel.misses = tot.misses - last.misses; + rel.allocations = tot.allocations - last.allocations; + rel.reclaims = tot.reclaims - last.reclaims; + rel.frees = tot.frees - last.frees; + printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n", + rel.lookups, rel.hits, rel.misses, + rel.allocations, rel.reclaims, rel.frees); + } + + if (!interval) + break; + + memcpy(&last, &tot, sizeof(last)); + sleep(interval); + + ret = lseek(fd, 0, 0); + if (ret < 0) + die("lseek"); + } + + close(fd); + return 0; +} diff --git a/libselinux/utils/compute_av.c b/libselinux/utils/compute_av.c new file mode 100644 index 00000000..574fa6ed --- /dev/null +++ b/libselinux/utils/compute_av.c @@ -0,0 +1,55 @@ +#include <unistd.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + struct av_decision avd; + security_class_t tclass; + int ret; + + if (argc != 4) { + fprintf(stderr, "usage: %s scontext tcontext tclass\n", + argv[0]); + exit(1); + } + + tclass = string_to_security_class(argv[3]); + if (!tclass) { + fprintf(stderr, "%s: invalid class '%s'\n", argv[0], argv[3]); + exit(2); + } + + ret = security_compute_av(argv[1], argv[2], tclass, 1, &avd); + if (ret < 0) { + fprintf(stderr, "%s: security_compute_av failed\n", argv[0]); + exit(3); + } + + printf("allowed="); + print_access_vector(tclass, avd.allowed); + printf("\n"); + + if (avd.decided != ~0U) { + printf("decided="); + print_access_vector(tclass, avd.decided); + printf("\n"); + } + + if (avd.auditallow) { + printf("auditallow="); + print_access_vector(tclass, avd.auditallow); + printf("\n"); + } + + if (avd.auditdeny != ~0U) { + printf("auditdeny"); + print_access_vector(tclass, avd.auditdeny); + printf("\n"); + } + + exit(0); +} diff --git a/libselinux/utils/compute_create.c b/libselinux/utils/compute_create.c new file mode 100644 index 00000000..4abc29fb --- /dev/null +++ b/libselinux/utils/compute_create.c @@ -0,0 +1,36 @@ +#include <unistd.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + char *buf; + security_class_t tclass; + int ret; + + if (argc != 4) { + fprintf(stderr, "usage: %s scontext tcontext tclass\n", + argv[0]); + exit(1); + } + + tclass = string_to_security_class(argv[3]); + if (!tclass) { + fprintf(stderr, "Invalid class '%s'\n", argv[3]); + exit(2); + } + + ret = security_compute_create(argv[1], argv[2], tclass, &buf); + if (ret < 0) { + fprintf(stderr, "%s: security_compute_create failed\n", + argv[0]); + exit(3); + } + + printf("%s\n", buf); + freecon(buf); + exit(0); +} diff --git a/libselinux/utils/compute_member.c b/libselinux/utils/compute_member.c new file mode 100644 index 00000000..14edd451 --- /dev/null +++ b/libselinux/utils/compute_member.c @@ -0,0 +1,36 @@ +#include <unistd.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + char *buf; + security_class_t tclass; + int ret; + + if (argc != 4) { + fprintf(stderr, "usage: %s scontext tcontext tclass\n", + argv[0]); + exit(1); + } + + tclass = string_to_security_class(argv[3]); + if (!tclass) { + fprintf(stderr, "Invalid class '%s'\n", argv[3]); + exit(2); + } + + ret = security_compute_member(argv[1], argv[2], tclass, &buf); + if (ret < 0) { + fprintf(stderr, "%s: security_compute_member failed\n", + argv[0]); + exit(3); + } + + printf("%s\n", buf); + freecon(buf); + exit(0); +} diff --git a/libselinux/utils/compute_relabel.c b/libselinux/utils/compute_relabel.c new file mode 100644 index 00000000..970750e8 --- /dev/null +++ b/libselinux/utils/compute_relabel.c @@ -0,0 +1,36 @@ +#include <unistd.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + char *buf; + security_class_t tclass; + int ret; + + if (argc != 4) { + fprintf(stderr, "usage: %s scontext tcontext tclass\n", + argv[0]); + exit(1); + } + + tclass = string_to_security_class(argv[3]); + if (!tclass) { + fprintf(stderr, "%s: invalid class '%s'\n", argv[0], argv[3]); + exit(2); + } + + ret = security_compute_relabel(argv[1], argv[2], tclass, &buf); + if (ret < 0) { + fprintf(stderr, "%s: security_compute_relabel failed\n", + argv[0]); + exit(3); + } + + printf("%s\n", buf); + freecon(buf); + exit(0); +} diff --git a/libselinux/utils/compute_user.c b/libselinux/utils/compute_user.c new file mode 100644 index 00000000..cae62b26 --- /dev/null +++ b/libselinux/utils/compute_user.c @@ -0,0 +1,38 @@ +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + char **buf, **ptr; + int ret; + + if (argc != 3) { + fprintf(stderr, "usage: %s context user\n", argv[0]); + exit(1); + } + + ret = security_compute_user(argv[1], argv[2], &buf); + if (ret < 0) { + fprintf(stderr, "%s: security_compute_user(%s,%s) failed\n", + argv[0], argv[1], argv[2]); + exit(2); + } + + if (!buf[0]) { + printf("none\n"); + exit(0); + } + + for (ptr = buf; *ptr; ptr++) { + printf("%s\n", *ptr); + } + freeconary(buf); + exit(0); +} diff --git a/libselinux/utils/getconlist.c b/libselinux/utils/getconlist.c new file mode 100644 index 00000000..4f473e4f --- /dev/null +++ b/libselinux/utils/getconlist.c @@ -0,0 +1,73 @@ +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <selinux/selinux.h> +#include <selinux/get_context_list.h> + +void usage(char *name, char *detail, int rc) +{ + fprintf(stderr, "usage: %s [-l level] user [context]\n", name); + if (detail) + fprintf(stderr, "%s: %s\n", name, detail); + exit(rc); +} + +int main(int argc, char **argv) +{ + security_context_t *list, usercon = NULL, cur_context = NULL; + char *user = NULL, *level = NULL; + int ret, i, opt; + + while ((opt = getopt(argc, argv, "l:")) > 0) { + switch (opt) { + case 'l': + level = strdup(optarg); + break; + default: + usage(argv[0], "invalid option", 1); + } + } + + if (((argc - optind) < 1) || ((argc - optind) > 2)) + usage(argv[0], "invalid number of arguments", 2); + + /* If selinux isn't available, bail out. */ + if (!is_selinux_enabled()) { + fprintf(stderr, + "getconlist may be used only on a SELinux kernel.\n"); + return 1; + } + + user = argv[optind]; + + /* If a context wasn't passed, use the current context. */ + if (((argc - optind) < 2)) { + if (getcon(&cur_context) < 0) { + fprintf(stderr, "Couldn't get current context.\n"); + return 2; + } + } else + cur_context = argv[optind + 1]; + + /* Get the list and print it */ + if (level) + ret = + get_ordered_context_list_with_level(user, level, + cur_context, &list); + else + ret = get_ordered_context_list(user, cur_context, &list); + if (ret != -1) { + for (i = 0; list[i]; i++) + puts(list[i]); + freeconary(list); + } + + free(usercon); + + return 0; +} diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c new file mode 100644 index 00000000..93762c1e --- /dev/null +++ b/libselinux/utils/getdefaultcon.c @@ -0,0 +1,80 @@ +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <selinux/selinux.h> +#include <selinux/get_context_list.h> + +void usage(char *name, char *detail, int rc) +{ + fprintf(stderr, "usage: %s [-l level] user fromcon\n", name); + if (detail) + fprintf(stderr, "%s: %s\n", name, detail); + exit(rc); +} + +int main(int argc, char **argv) +{ + security_context_t usercon = NULL, cur_context = NULL; + char *user = NULL, *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL; + int ret, opt; + + while ((opt = getopt(argc, argv, "l:r:")) > 0) { + switch (opt) { + case 'l': + level = strdup(optarg); + break; + case 'r': + role = strdup(optarg); + break; + default: + usage(argv[0], "invalid option", 1); + } + } + + if (((argc - optind) < 1) || ((argc - optind) > 2)) + usage(argv[0], "invalid number of arguments", 2); + + /* If selinux isn't available, bail out. */ + if (!is_selinux_enabled()) { + fprintf(stderr, + "%s may be used only on a SELinux kernel.\n", argv[0]); + return 1; + } + + user = argv[optind]; + + /* If a context wasn't passed, use the current context. */ + if (((argc - optind) < 2)) { + if (getcon(&cur_context) < 0) { + fprintf(stderr, "Couldn't get current context.\n"); + return 2; + } + } else + cur_context = argv[optind + 1]; + + if ((ret = getseuserbyname(user, &seuser, &dlevel)) == 0) { + if (! level) level=dlevel; + if (role != NULL && role[0]) + ret=get_default_context_with_rolelevel(seuser, role, level,cur_context,&usercon); + else + ret=get_default_context_with_level(seuser, level, cur_context,&usercon); + } + if (ret < 0) + perror(argv[0]); + else + printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon); + + + free(role); + free(seuser); + if (level != dlevel) free(level); + free(dlevel); + free(usercon); + + return 0; +} diff --git a/libselinux/utils/getenforce.c b/libselinux/utils/getenforce.c new file mode 100644 index 00000000..891c7b7e --- /dev/null +++ b/libselinux/utils/getenforce.c @@ -0,0 +1,31 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <selinux/selinux.h> + +int main(int argc __attribute__ ((unused)), char **argv) +{ + int rc; + + rc = is_selinux_enabled(); + if (rc < 0) { + fputs("getenforce: is_selinux_enabled() failed", stderr); + return 2; + } + if (rc == 1) { + rc = security_getenforce(); + if (rc < 0) { + fputs("getenforce: getenforce() failed", stderr); + return 2; + } + + if (rc) + puts("Enforcing"); + else + puts("Permissive"); + } else { + puts("Disabled"); + } + + return 0; +} diff --git a/libselinux/utils/getfilecon.c b/libselinux/utils/getfilecon.c new file mode 100644 index 00000000..a7a51abb --- /dev/null +++ b/libselinux/utils/getfilecon.c @@ -0,0 +1,27 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + char *buf; + int rc, i; + + if (argc < 2) { + fprintf(stderr, "usage: %s path...\n", argv[0]); + exit(1); + } + + for (i = 1; i < argc; i++) { + rc = getfilecon(argv[i], &buf); + if (rc < 0) { + fprintf(stderr, "%s: getfilecon(%s) failed\n", argv[0], + argv[i]); + exit(2); + } + printf("%s\t%s\n", argv[i], buf); + freecon(buf); + } + exit(0); +} diff --git a/libselinux/utils/getpidcon.c b/libselinux/utils/getpidcon.c new file mode 100644 index 00000000..3df0da1f --- /dev/null +++ b/libselinux/utils/getpidcon.c @@ -0,0 +1,31 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + pid_t pid; + char *buf; + int rc; + + if (argc != 2) { + fprintf(stderr, "usage: %s pid\n", argv[0]); + exit(1); + } + + if (sscanf(argv[1], "%d", &pid) != 1) { + fprintf(stderr, "%s: invalid pid %s\n", argv[0], argv[1]); + exit(2); + } + + rc = getpidcon(pid, &buf); + if (rc < 0) { + fprintf(stderr, "%s: getpidcon() failed\n", argv[0]); + exit(3); + } + + printf("%s\n", buf); + freecon(buf); + exit(0); +} diff --git a/libselinux/utils/getsebool.c b/libselinux/utils/getsebool.c new file mode 100644 index 00000000..cab2bb9c --- /dev/null +++ b/libselinux/utils/getsebool.c @@ -0,0 +1,105 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <getopt.h> +#include <errno.h> +#include <string.h> +#include <selinux/selinux.h> + +void usage(const char *progname) +{ + fprintf(stderr, "usage: %s -a or %s boolean...\n", progname, progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int i, get_all = 0, rc = 0, active, pending, len = 0, opt; + char **names; + + while ((opt = getopt(argc, argv, "a")) > 0) { + switch (opt) { + case 'a': + if (argc > 2) + usage(argv[0]); + if (is_selinux_enabled() <= 0) { + fprintf(stderr, "%s: SELinux is disabled\n", + argv[0]); + return 1; + } + errno = 0; + rc = security_get_boolean_names(&names, &len); + if (rc) { + fprintf(stderr, + "%s: Unable to get boolean names: %s\n", + argv[0], strerror(errno)); + return 1; + } + if (!len) { + printf("No booleans\n"); + return 0; + } + get_all = 1; + break; + default: + usage(argv[0]); + } + } + + if (is_selinux_enabled() <= 0) { + fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); + return 1; + } + + if (!len) { + if (argc < 2) + usage(argv[0]); + len = argc - 1; + names = malloc(sizeof(char *) * len); + if (!names) { + fprintf(stderr, "%s: out of memory\n", argv[0]); + return 2; + } + for (i = 0; i < len; i++) { + names[i] = strdup(argv[i + 1]); + if (!names[i]) { + fprintf(stderr, "%s: out of memory\n", + argv[0]); + return 2; + } + } + } + + for (i = 0; i < len; i++) { + active = security_get_boolean_active(names[i]); + if (active < 0) { + if (get_all && errno == EACCES) + continue; + fprintf(stderr, "Error getting active value for %s\n", + names[i]); + rc = -1; + goto out; + } + pending = security_get_boolean_pending(names[i]); + if (pending < 0) { + fprintf(stderr, "Error getting pending value for %s\n", + names[i]); + rc = -1; + goto out; + } + if (pending != active) { + printf("%s --> %s pending: %s\n", names[i], + (active ? "on" : "off"), + (pending ? "on" : "off")); + } else { + printf("%s --> %s\n", names[i], + (active ? "on" : "off")); + } + } + + out: + for (i = 0; i < len; i++) + free(names[i]); + free(names); + return rc; +} diff --git a/libselinux/utils/getseuser.c b/libselinux/utils/getseuser.c new file mode 100644 index 00000000..1e7ed765 --- /dev/null +++ b/libselinux/utils/getseuser.c @@ -0,0 +1,40 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <selinux/selinux.h> +#include <selinux/get_context_list.h> + +int main(int argc, char **argv) +{ + char *seuser = NULL, *level = NULL; + security_context_t *contextlist; + int rc, n, i; + + if (argc != 3) { + fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]); + exit(1); + } + + rc = getseuserbyname(argv[1], &seuser, &level); + if (rc) { + fprintf(stderr, "getseuserbyname failed: %s\n", + strerror(errno)); + exit(2); + } + printf("seuser: %s, level %s\n", seuser, level); + n = get_ordered_context_list_with_level(seuser, level, argv[2], + &contextlist); + if (n <= 0) { + fprintf(stderr, + "get_ordered_context_list_with_level failed: %s\n", + strerror(errno)); + exit(3); + } + free(seuser); + free(level); + for (i = 0; i < n; i++) + printf("Context %d\t%s\n", i, contextlist[i]); + freeconary(contextlist); + exit(0); +} diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c new file mode 100644 index 00000000..5276d24d --- /dev/null +++ b/libselinux/utils/matchpathcon.c @@ -0,0 +1,143 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/errno.h> +#include <selinux/selinux.h> + +void usage(const char *progname) +{ + fprintf(stderr, + "usage: %s [-N] [-n] [-f file_contexts] [-p prefix] [-Vq] path...\n", + progname); + exit(1); +} + +int printmatchpathcon(char *path, int header, int mode) +{ + char *buf; + int rc = matchpathcon(path, mode, &buf); + if (rc < 0) { + fprintf(stderr, "matchpathcon(%s) failed: %s\n", path, + strerror(errno)); + return 1; + } + if (header) + printf("%s\t%s\n", path, buf); + else + printf("%s\n", buf); + + freecon(buf); + return 0; +} + +int main(int argc, char **argv) +{ + int i, init = 0; + int header = 1, opt; + int verify = 0; + int notrans = 0; + int error = 0; + int quiet = 0; + + if (argc < 2) + usage(argv[0]); + + while ((opt = getopt(argc, argv, "Nnf:p:Vq")) > 0) { + switch (opt) { + case 'n': + header = 0; + break; + case 'V': + verify = 1; + break; + case 'N': + notrans = 1; + set_matchpathcon_flags(MATCHPATHCON_NOTRANS); + break; + case 'f': + if (init) { + fprintf(stderr, + "%s: -f and -p are exclusive\n", + argv[0]); + exit(1); + } + init = 1; + if (matchpathcon_init(optarg)) { + fprintf(stderr, + "Error while processing %s: %s\n", + optarg, + errno ? strerror(errno) : "invalid"); + exit(1); + } + break; + case 'p': + if (init) { + fprintf(stderr, + "%s: -f and -p are exclusive\n", + argv[0]); + exit(1); + } + init = 1; + if (matchpathcon_init_prefix(NULL, optarg)) { + fprintf(stderr, + "Error while processing %s: %s\n", + optarg, + errno ? strerror(errno) : "invalid"); + exit(1); + } + break; + case 'q': + quiet = 1; + break; + default: + usage(argv[0]); + } + } + for (i = optind; i < argc; i++) { + int mode = 0; + struct stat buf; + if (lstat(argv[i], &buf) == 0) + mode = buf.st_mode; + + if (verify) { + if (quiet) { + if (selinux_file_context_verify(argv[i], 0)) + continue; + else + exit(1); + } + if (selinux_file_context_verify(argv[i], 0)) { + printf("%s verified.\n", argv[i]); + } else { + security_context_t con; + int rc; + error = 1; + if (notrans) + rc = lgetfilecon_raw(argv[i], &con); + else + rc = lgetfilecon(argv[i], &con); + + if (rc >= 0) { + printf("%s has context %s, should be ", + argv[i], con); + printmatchpathcon(argv[i], 0, mode); + freecon(con); + } else { + printf + ("actual context unknown: %s, should be ", + strerror(errno)); + printmatchpathcon(argv[i], 0, mode); + } + } + } else { + error |= printmatchpathcon(argv[i], header, mode); + } + } + matchpathcon_fini(); + return error; +} diff --git a/libselinux/utils/policyvers.c b/libselinux/utils/policyvers.c new file mode 100644 index 00000000..0309d7d1 --- /dev/null +++ b/libselinux/utils/policyvers.c @@ -0,0 +1,18 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <selinux/selinux.h> + +int main(int argc __attribute__ ((unused)), char **argv) +{ + int rc; + + rc = security_policyvers(); + if (rc < 0) { + fprintf(stderr, "%s: policyvers() failed\n", argv[0]); + exit(2); + } + + printf("%d\n", rc); + exit(0); +} diff --git a/libselinux/utils/selinux_check_securetty_context.c b/libselinux/utils/selinux_check_securetty_context.c new file mode 100644 index 00000000..95bfb7f2 --- /dev/null +++ b/libselinux/utils/selinux_check_securetty_context.c @@ -0,0 +1,35 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/errno.h> +#include <selinux/selinux.h> + +void usage(const char *progname) +{ + fprintf(stderr, "usage: %s tty_context...\n", progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int i; + if (argc < 2) + usage(argv[0]); + + for (i = 1; i < argc; i++) { + switch (selinux_check_securetty_context(argv[i])) { + case 0: + printf("%s securetty.\n", argv[i]); + break; + default: + printf("%s not securetty.\n", argv[i]); + break; + } + } + return 0; +} diff --git a/libselinux/utils/selinuxenabled.c b/libselinux/utils/selinuxenabled.c new file mode 100644 index 00000000..04ea7783 --- /dev/null +++ b/libselinux/utils/selinuxenabled.c @@ -0,0 +1,9 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <selinux/selinux.h> + +int main(void) +{ + return !is_selinux_enabled(); +} diff --git a/libselinux/utils/setenforce.c b/libselinux/utils/setenforce.c new file mode 100644 index 00000000..e45b804d --- /dev/null +++ b/libselinux/utils/setenforce.c @@ -0,0 +1,42 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <selinux/selinux.h> + +void usage(const char *progname) +{ + fprintf(stderr, "usage: %s [ Enforcing | Permissive | 1 | 0 ]\n", + progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int rc = 0; + if (argc != 2) { + usage(argv[0]); + } + + if (is_selinux_enabled() <= 0) { + fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); + return 1; + } + if (strlen(argv[1]) == 1 && (argv[1][0] == '0' || argv[1][0] == '1')) { + rc = security_setenforce(atoi(argv[1])); + } else { + if (strcasecmp(argv[1], "enforcing") == 0) { + rc = security_setenforce(1); + } else if (strcasecmp(argv[1], "permissive") == 0) { + rc = security_setenforce(0); + } else + usage(argv[0]); + } + if (rc < 0) { + fprintf(stderr, "%s: setenforce() failed\n", argv[0]); + return 2; + } + return 0; +} diff --git a/libselinux/utils/setfilecon.c b/libselinux/utils/setfilecon.c new file mode 100644 index 00000000..d69af84a --- /dev/null +++ b/libselinux/utils/setfilecon.c @@ -0,0 +1,24 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <selinux/selinux.h> + +int main(int argc, char **argv) +{ + int rc, i; + + if (argc < 3) { + fprintf(stderr, "usage: %s context path...\n", argv[0]); + exit(1); + } + + for (i = 2; i < argc; i++) { + rc = setfilecon(argv[i], argv[1]); + if (rc < 0) { + fprintf(stderr, "%s: setfilecon(%s,%s) failed\n", + argv[0], argv[i], argv[1]); + exit(2); + } + } + exit(0); +} diff --git a/libselinux/utils/togglesebool.c b/libselinux/utils/togglesebool.c new file mode 100644 index 00000000..680ed8d0 --- /dev/null +++ b/libselinux/utils/togglesebool.c @@ -0,0 +1,97 @@ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <libgen.h> +#include <errno.h> +#include <selinux/selinux.h> +#include <syslog.h> +#include <pwd.h> +#include <string.h> + +/* Attempt to rollback the transaction. No need to check error + codes since this is rolling back something that blew up. */ +void rollback(int argc, char **argv) +{ + int i; + + for (i = 1; i < argc; i++) + security_set_boolean(argv[i], + security_get_boolean_active(argv[i])); + exit(1); +} + +int main(int argc, char **argv) +{ + + int rc, i, commit = 0; + + if (is_selinux_enabled() <= 0) { + fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); + return 1; + } + + if (argc < 2) { + printf("Usage: %s boolname1 [boolname2 ...]\n", + basename(argv[0])); + return 1; + } + + for (i = 1; i < argc; i++) { + printf("%s: ", argv[i]); + rc = security_get_boolean_active(argv[i]); + switch (rc) { + case 1: + if (security_set_boolean(argv[i], 0) >= 0) { + printf("inactive\n"); + commit++; + } else { + printf("%s - rolling back all changes\n", + strerror(errno)); + rollback(i, argv); + } + break; + case 0: + if (security_set_boolean(argv[i], 1) >= 0) { + printf("active\n"); + commit++; + } else { + printf("%s - rolling back all changes\n", + strerror(errno)); + rollback(i, argv); + } + break; + default: + if (errno == ENOENT) + printf + ("Boolean does not exist - rolling back all changes.\n"); + else + printf("%s - rolling back all changes.\n", + strerror(errno)); + rollback(i, argv); + break; /* Not reached. */ + } + } + + if (commit > 0) { + if (security_commit_booleans() < 0) { + printf("Commit failed. (%s) No change to booleans.\n", + strerror(errno)); + } else { + /* syslog all the changes */ + struct passwd *pwd = getpwuid(getuid()); + for (i = 1; i < argc; i++) { + if (pwd && pwd->pw_name) + syslog(LOG_NOTICE, + "The %s policy boolean was toggled by %s", + argv[i], pwd->pw_name); + else + syslog(LOG_NOTICE, + "The %s policy boolean was toggled by uid:%d", + argv[i], getuid()); + + } + return 0; + } + } + return 1; +} |