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