• 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 <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