Home | History | Annotate | Download | only in utils
      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 
     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 
     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 
     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 
     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