• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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