• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <getopt.h>
5 #include <errno.h>
6 #include <stdbool.h>
7 #include <fts.h>
8 #include <selinux/selinux.h>
9 #include <selinux/label.h>
10 
11 #include "../src/label_file.h"
12 
usage(const char * progname)13 static __attribute__ ((__noreturn__)) void usage(const char *progname)
14 {
15 	fprintf(stderr,
16 		"usage:  %s [-vr] [-f file] path\n\n"
17 		"Where:\n\t"
18 		"-v  Validate file_contxts entries against loaded policy.\n\t"
19 		"-r  Recursively descend directories.\n\t"
20 		"-f  Optional file_contexts file (defaults to current policy).\n\t"
21 		"path  Path to check current SHA1 digest against file_contexts entries.\n\n"
22 		"This will check the directory selinux.sehash SHA1 digest for "
23 		"<path> against\na newly generated digest based on the "
24 		"file_context entries for that node\n(using the regx, mode "
25 		"and path entries).\n", progname);
26 	exit(1);
27 }
28 
main(int argc,char ** argv)29 int main(int argc, char **argv)
30 {
31 	int opt, fts_flags;
32 	size_t i, digest_len;
33 	bool status, recurse = false;
34 	FTS *fts;
35 	FTSENT *ftsent;
36 	char *validate = NULL, *file = NULL;
37 	char *paths[2] = { NULL, NULL };
38 	uint8_t *xattr_digest = NULL;
39 	uint8_t *calculated_digest = NULL;
40 	char *sha1_buf = NULL;
41 
42 	struct selabel_handle *hnd;
43 	struct selinux_opt selabel_option[] = {
44 		{ SELABEL_OPT_PATH, file },
45 		{ SELABEL_OPT_VALIDATE, validate }
46 	};
47 
48 	if (argc < 2)
49 		usage(argv[0]);
50 
51 	while ((opt = getopt(argc, argv, "f:rv")) > 0) {
52 		switch (opt) {
53 		case 'f':
54 			file = optarg;
55 			break;
56 		case 'r':
57 			recurse = true;
58 			break;
59 		case 'v':
60 			validate = (char *)1;
61 			break;
62 		default:
63 			usage(argv[0]);
64 		}
65 	}
66 
67 	if (optind >= argc) {
68 		fprintf(stderr, "No pathname specified\n");
69 		exit(-1);
70 	}
71 
72 	paths[0] = argv[optind];
73 
74 	selabel_option[0].value = file;
75 	selabel_option[1].value = validate;
76 
77 	hnd = selabel_open(SELABEL_CTX_FILE, selabel_option, 2);
78 	if (!hnd) {
79 		fprintf(stderr, "ERROR: selabel_open - Could not obtain "
80 							     "handle.\n");
81 		return -1;
82 	}
83 
84 	fts_flags = FTS_PHYSICAL | FTS_NOCHDIR;
85 	fts = fts_open(paths, fts_flags, NULL);
86 	if (!fts) {
87 		printf("fts error on %s: %s\n",
88 		       paths[0], strerror(errno));
89 		return -1;
90 	}
91 
92 	while ((ftsent = fts_read(fts)) != NULL) {
93 		switch (ftsent->fts_info) {
94 		case FTS_DP:
95 			continue;
96 		case FTS_D: {
97 
98 			xattr_digest = NULL;
99 			calculated_digest = NULL;
100 			digest_len = 0;
101 
102 			status = selabel_get_digests_all_partial_matches(hnd,
103 							 ftsent->fts_path,
104 							 &calculated_digest,
105 							 &xattr_digest,
106 							 &digest_len);
107 
108 			sha1_buf = calloc(1, digest_len * 2 + 1);
109 			if (!sha1_buf) {
110 				fprintf(stderr, "Could not calloc buffer ERROR: %s\n",
111 					    strerror(errno));
112 				return -1;
113 			}
114 
115 			if (status) { /* They match */
116 				printf("xattr and file_contexts SHA1 digests match for: %s\n",
117 				       ftsent->fts_path);
118 
119 				if (calculated_digest) {
120 					for (i = 0; i < digest_len; i++)
121 						sprintf((&sha1_buf[i * 2]),
122 							"%02x",
123 							calculated_digest[i]);
124 					printf("SHA1 digest: %s\n", sha1_buf);
125 				}
126 			} else {
127 				if (!calculated_digest) {
128 					printf("No SHA1 digest available for: %s\n",
129 					       ftsent->fts_path);
130 					printf("as file_context entry is \"<<none>>\"\n");
131 					goto cleanup;
132 				}
133 
134 				printf("The file_context entries for: %s\n",
135 				       ftsent->fts_path);
136 
137 				for (i = 0; i < digest_len; i++)
138 					sprintf((&sha1_buf[i * 2]), "%02x",
139 						calculated_digest[i]);
140 				printf("generated SHA1 digest: %s\n", sha1_buf);
141 
142 				if (!xattr_digest) {
143 					printf("however there is no selinux.sehash xattr entry.\n");
144 				} else {
145 					printf("however it does NOT match the current entry of:\n");
146 					for (i = 0; i < digest_len; i++)
147 						sprintf((&sha1_buf[i * 2]),
148 							"%02x",
149 							xattr_digest[i]);
150 					printf("%s\n", sha1_buf);
151 				}
152 			}
153 			cleanup:
154 			free(xattr_digest);
155 			free(calculated_digest);
156 			free(sha1_buf);
157 			break;
158 		}
159 		default:
160 			break;
161 		}
162 
163 		if (!recurse)
164 			break;
165 	}
166 
167 	(void) fts_close(fts);
168 	(void) selabel_close(hnd);
169 	return 0;
170 }
171