1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <getopt.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <limits.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/errno.h>
11 #include <selinux/selinux.h>
12 #include <limits.h>
13 #include <stdlib.h>
14
usage(const char * progname)15 static void usage(const char *progname)
16 {
17 fprintf(stderr,
18 "usage: %s [-N] [-n] [-f file_contexts] [ -P policy_root_path ] [-p prefix] [-Vq] path...\n",
19 progname);
20 exit(1);
21 }
22
printmatchpathcon(const char * path,int header,int mode)23 static int printmatchpathcon(const char *path, int header, int mode)
24 {
25 char *buf;
26 int rc = matchpathcon(path, mode, &buf);
27 if (rc < 0) {
28 if (errno == ENOENT) {
29 buf=strdup("<<none>>");
30 } else {
31 fprintf(stderr, "matchpathcon(%s) failed: %s\n", path,
32 strerror(errno));
33 return 1;
34 }
35 }
36 if (header)
37 printf("%s\t%s\n", path, buf);
38 else
39 printf("%s\n", buf);
40
41 freecon(buf);
42 return 0;
43 }
44
string_to_mode(char * s)45 static mode_t string_to_mode(char *s)
46 {
47 switch (s[0]) {
48 case 'b':
49 return S_IFBLK;
50 case 'c':
51 return S_IFCHR;
52 case 'd':
53 return S_IFDIR;
54 case 'p':
55 return S_IFIFO;
56 case 'l':
57 return S_IFLNK;
58 case 's':
59 return S_IFSOCK;
60 case 'f':
61 return S_IFREG;
62 default:
63 return -1;
64 };
65 return -1;
66 }
67
main(int argc,char ** argv)68 int main(int argc, char **argv)
69 {
70 int i, init = 0, force_mode = 0;
71 int header = 1, opt;
72 int verify = 0;
73 int notrans = 0;
74 int error = 0;
75 int quiet = 0;
76
77 if (argc < 2)
78 usage(argv[0]);
79
80 while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) {
81 switch (opt) {
82 case 'n':
83 header = 0;
84 break;
85 case 'm':
86 force_mode = string_to_mode(optarg);
87 if (force_mode < 0) {
88 fprintf(stderr, "%s: mode %s is invalid\n", argv[0], optarg);
89 exit(1);
90 }
91 break;
92 case 'V':
93 verify = 1;
94 break;
95 case 'N':
96 notrans = 1;
97 set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
98 break;
99 case 'f':
100 if (init) {
101 fprintf(stderr,
102 "%s: -f and -p are exclusive\n",
103 argv[0]);
104 exit(1);
105 }
106 init = 1;
107 if (matchpathcon_init(optarg)) {
108 fprintf(stderr,
109 "Error while processing %s: %s\n",
110 optarg,
111 errno ? strerror(errno) : "invalid");
112 exit(1);
113 }
114 break;
115 case 'P':
116 if (selinux_set_policy_root(optarg) < 0 ) {
117 fprintf(stderr,
118 "Error setting policy root %s: %s\n",
119 optarg,
120 errno ? strerror(errno) : "invalid");
121 exit(1);
122 }
123 break;
124 case 'p':
125 if (init) {
126 fprintf(stderr,
127 "%s: -f and -p are exclusive\n",
128 argv[0]);
129 exit(1);
130 }
131 init = 1;
132 if (matchpathcon_init_prefix(NULL, optarg)) {
133 fprintf(stderr,
134 "Error while processing %s: %s\n",
135 optarg,
136 errno ? strerror(errno) : "invalid");
137 exit(1);
138 }
139 break;
140 case 'q':
141 quiet = 1;
142 break;
143 default:
144 usage(argv[0]);
145 }
146 }
147 for (i = optind; i < argc; i++) {
148 int rc, mode = 0;
149 struct stat buf;
150 char *path = argv[i];
151 int len = strlen(path);
152 if (len > 1 && path[len - 1 ] == '/')
153 path[len - 1 ] = '\0';
154
155 if (lstat(path, &buf) == 0)
156 mode = buf.st_mode;
157 if (force_mode)
158 mode = force_mode;
159
160 if (verify) {
161 rc = selinux_file_context_verify(path, mode);
162
163 if (quiet) {
164 if (rc == 1)
165 continue;
166 else
167 exit(1);
168 }
169
170 if (rc == -1) {
171 printf("%s error: %s\n", path, strerror(errno));
172 exit(1);
173 } else if (rc == 1) {
174 printf("%s verified.\n", path);
175 } else {
176 char * con;
177 error = 1;
178 if (notrans)
179 rc = lgetfilecon_raw(path, &con);
180 else
181 rc = lgetfilecon(path, &con);
182
183 if (rc >= 0) {
184 printf("%s has context %s, should be ",
185 path, con);
186 printmatchpathcon(path, 0, mode);
187 freecon(con);
188 } else {
189 printf
190 ("actual context unknown: %s, should be ",
191 strerror(errno));
192 printmatchpathcon(path, 0, mode);
193 }
194 }
195 } else {
196 error |= printmatchpathcon(path, header, mode);
197 }
198 }
199 matchpathcon_fini();
200 return error;
201 }
202