unzip: use printable_string() for printing filenames
[oweals/busybox.git] / selinux / sestatus.c
1 /*
2  * sestatus -- displays the status of SELinux
3  *
4  * Ported to busybox: KaiGai Kohei <kaigai@ak.jp.nec.com>
5  *
6  * Copyright (C) KaiGai Kohei <kaigai@ak.jp.nec.com>
7  *
8  * Licensed under GPLv2, see file LICENSE in this source tree.
9  */
10 //config:config SESTATUS
11 //config:       bool "sestatus (12 kb)"
12 //config:       default n
13 //config:       depends on SELINUX
14 //config:       help
15 //config:       Displays the status of SELinux.
16
17 //applet:IF_SESTATUS(APPLET(sestatus, BB_DIR_USR_SBIN, BB_SUID_DROP))
18
19 //kbuild:lib-$(CONFIG_SESTATUS) += sestatus.o
20
21 //usage:#define sestatus_trivial_usage
22 //usage:       "[-vb]"
23 //usage:#define sestatus_full_usage "\n\n"
24 //usage:       "        -v      Verbose"
25 //usage:     "\n        -b      Display current state of booleans"
26
27 #include "libbb.h"
28
29 extern char *selinux_mnt;
30
31 #define OPT_VERBOSE  (1 << 0)
32 #define OPT_BOOLEAN  (1 << 1)
33
34 #define COL_FMT  "%-31s "
35
36 static void display_boolean(void)
37 {
38         char **bools;
39         int i, active, pending, nbool;
40
41         if (security_get_boolean_names(&bools, &nbool) < 0)
42                 return;
43
44         puts("\nPolicy booleans:");
45
46         for (i = 0; i < nbool; i++) {
47                 active = security_get_boolean_active(bools[i]);
48                 if (active < 0)
49                         goto skip;
50                 pending = security_get_boolean_pending(bools[i]);
51                 if (pending < 0)
52                         goto skip;
53                 printf(COL_FMT "%s",
54                                 bools[i], active == 0 ? "off" : "on");
55                 if (active != pending)
56                         printf(" (%sactivate pending)", pending == 0 ? "in" : "");
57                 bb_putchar('\n');
58  skip:
59                 if (ENABLE_FEATURE_CLEAN_UP)
60                         free(bools[i]);
61         }
62         if (ENABLE_FEATURE_CLEAN_UP)
63                 free(bools);
64 }
65
66 static void read_config(char **pc, int npc, char **fc, int nfc)
67 {
68         char *buf;
69         parser_t *parser;
70         int pc_ofs = 0, fc_ofs = 0, section = -1;
71
72         pc[0] = fc[0] = NULL;
73
74         parser = config_open("/etc/sestatus.conf");
75         while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
76                 if (strcmp(buf, "[process]") == 0) {
77                         section = 1;
78                 } else if (strcmp(buf, "[files]") == 0) {
79                         section = 2;
80                 } else {
81                         if (section == 1 && pc_ofs < npc -1) {
82                                 pc[pc_ofs++] = xstrdup(buf);
83                                 pc[pc_ofs] = NULL;
84                         } else if (section == 2 && fc_ofs < nfc - 1) {
85                                 fc[fc_ofs++] = xstrdup(buf);
86                                 fc[fc_ofs] = NULL;
87                         }
88                 }
89         }
90         config_close(parser);
91 }
92
93 static void display_verbose(void)
94 {
95         security_context_t con, _con;
96         char *fc[50], *pc[50], *cterm;
97         pid_t *pidList;
98         int i;
99
100         read_config(pc, ARRAY_SIZE(pc), fc, ARRAY_SIZE(fc));
101
102         /* process contexts */
103         puts("\nProcess contexts:");
104
105         /* current context */
106         if (getcon(&con) == 0) {
107                 printf(COL_FMT "%s\n", "Current context:", con);
108                 if (ENABLE_FEATURE_CLEAN_UP)
109                         freecon(con);
110         }
111         /* /sbin/init context */
112         if (getpidcon(1, &con) == 0) {
113                 printf(COL_FMT "%s\n", "Init context:", con);
114                 if (ENABLE_FEATURE_CLEAN_UP)
115                         freecon(con);
116         }
117
118         /* [process] context */
119         for (i = 0; pc[i] != NULL; i++) {
120                 pidList = find_pid_by_name(bb_basename(pc[i]));
121                 if (pidList[0] > 0 && getpidcon(pidList[0], &con) == 0) {
122                         printf(COL_FMT "%s\n", pc[i], con);
123                         if (ENABLE_FEATURE_CLEAN_UP)
124                                 freecon(con);
125                 }
126                 if (ENABLE_FEATURE_CLEAN_UP)
127                         free(pidList);
128         }
129
130         /* files contexts */
131         puts("\nFile contexts:");
132
133         cterm = xmalloc_ttyname(0);
134 //FIXME: if cterm == NULL, we segfault!??
135         puts(cterm);
136         if (cterm && lgetfilecon(cterm, &con) >= 0) {
137                 printf(COL_FMT "%s\n", "Controlling term:", con);
138                 if (ENABLE_FEATURE_CLEAN_UP)
139                         freecon(con);
140         }
141
142         for (i = 0; fc[i] != NULL; i++) {
143                 struct stat stbuf;
144
145                 if (lgetfilecon(fc[i], &con) < 0)
146                         continue;
147                 if (lstat(fc[i], &stbuf) == 0) {
148                         if (S_ISLNK(stbuf.st_mode)) {
149                                 if (getfilecon(fc[i], &_con) >= 0) {
150                                         printf(COL_FMT "%s -> %s\n", fc[i], _con, con);
151                                         if (ENABLE_FEATURE_CLEAN_UP)
152                                                 freecon(_con);
153                                 }
154                         } else {
155                                 printf(COL_FMT "%s\n", fc[i], con);
156                         }
157                 }
158                 if (ENABLE_FEATURE_CLEAN_UP)
159                         freecon(con);
160         }
161 }
162
163 int sestatus_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
164 int sestatus_main(int argc UNUSED_PARAM, char **argv)
165 {
166         unsigned opts;
167         const char *pol_path;
168         int rc;
169
170         opts = getopt32(argv, "^" "vb" "\0" "=0"/*no arguments*/);
171
172         /* SELinux status: line */
173         rc = is_selinux_enabled();
174         if (rc < 0)
175                 goto error;
176         printf(COL_FMT "%s\n", "SELinux status:",
177                rc == 1 ? "enabled" : "disabled");
178
179         /* SELinuxfs mount: line */
180         if (!selinux_mnt)
181                 goto error;
182         printf(COL_FMT "%s\n", "SELinuxfs mount:",
183                selinux_mnt);
184
185         /* Current mode: line */
186         rc = security_getenforce();
187         if (rc < 0)
188                 goto error;
189         printf(COL_FMT "%s\n", "Current mode:",
190                rc == 0 ? "permissive" : "enforcing");
191
192         /* Mode from config file: line */
193         if (selinux_getenforcemode(&rc) != 0)
194                 goto error;
195         printf(COL_FMT "%s\n", "Mode from config file:",
196                rc < 0 ? "disabled" : (rc == 0 ? "permissive" : "enforcing"));
197
198         /* Policy version: line */
199         rc = security_policyvers();
200         if (rc < 0)
201                 goto error;
202         printf(COL_FMT "%u\n", "Policy version:", rc);
203
204         /* Policy from config file: line */
205         pol_path = selinux_policy_root();
206         if (!pol_path)
207                 goto error;
208         printf(COL_FMT "%s\n", "Policy from config file:",
209                bb_basename(pol_path));
210
211         if (opts & OPT_BOOLEAN)
212                 display_boolean();
213         if (opts & OPT_VERBOSE)
214                 display_verbose();
215
216         return 0;
217
218   error:
219         bb_perror_msg_and_die("libselinux returns unknown state");
220 }