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