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 <selinux/selinux.h>
     11 #include <limits.h>
     12 #include <stdlib.h>
     13 
     14 static __attribute__ ((__noreturn__)) void usage(const char *progname)
     15 {
     16 	fprintf(stderr,
     17 		"usage:  %s [-N] [-n] [-f file_contexts] [ -P policy_root_path ] [-p prefix] [-Vq] path...\n",
     18 		progname);
     19 	exit(1);
     20 }
     21 
     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 
     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 
     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