1*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
2*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
3*2d543d20SAndroid Build Coastguard Worker #include <string.h>
4*2d543d20SAndroid Build Coastguard Worker #include <getopt.h>
5*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
6*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
7*2d543d20SAndroid Build Coastguard Worker #include <selinux/label.h>
8*2d543d20SAndroid Build Coastguard Worker
usage(const char * progname)9*2d543d20SAndroid Build Coastguard Worker static __attribute__ ((__noreturn__)) void usage(const char *progname)
10*2d543d20SAndroid Build Coastguard Worker {
11*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
12*2d543d20SAndroid Build Coastguard Worker "usage: %s -b backend [-v] [-B] [-i] [-f file]\n\n"
13*2d543d20SAndroid Build Coastguard Worker "Where:\n\t"
14*2d543d20SAndroid Build Coastguard Worker "-b The backend - \"file\", \"media\", \"x\", \"db\" or "
15*2d543d20SAndroid Build Coastguard Worker "\"prop\"\n\t"
16*2d543d20SAndroid Build Coastguard Worker "-v Run \"cat <specfile_list> | openssl dgst -sha1 -hex\"\n\t"
17*2d543d20SAndroid Build Coastguard Worker " on the list of specfiles to compare the SHA1 digests.\n\t"
18*2d543d20SAndroid Build Coastguard Worker "-B Use base specfiles only (valid for \"-b file\" only).\n\t"
19*2d543d20SAndroid Build Coastguard Worker "-i Do not request a digest.\n\t"
20*2d543d20SAndroid Build Coastguard Worker "-f Optional file containing the specs (defaults to\n\t"
21*2d543d20SAndroid Build Coastguard Worker " those used by loaded policy).\n\n",
22*2d543d20SAndroid Build Coastguard Worker progname);
23*2d543d20SAndroid Build Coastguard Worker exit(1);
24*2d543d20SAndroid Build Coastguard Worker }
25*2d543d20SAndroid Build Coastguard Worker
run_check_digest(const char * cmd,const char * selabel_digest,size_t digest_len)26*2d543d20SAndroid Build Coastguard Worker static int run_check_digest(const char *cmd, const char *selabel_digest, size_t digest_len)
27*2d543d20SAndroid Build Coastguard Worker {
28*2d543d20SAndroid Build Coastguard Worker FILE *fp;
29*2d543d20SAndroid Build Coastguard Worker char files_digest[128];
30*2d543d20SAndroid Build Coastguard Worker const char *files_ptr;
31*2d543d20SAndroid Build Coastguard Worker int rc = 0;
32*2d543d20SAndroid Build Coastguard Worker
33*2d543d20SAndroid Build Coastguard Worker fp = popen(cmd, "r");
34*2d543d20SAndroid Build Coastguard Worker if (!fp) {
35*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Failed to run command '%s': %s\n", cmd, strerror(errno));
36*2d543d20SAndroid Build Coastguard Worker return -1;
37*2d543d20SAndroid Build Coastguard Worker }
38*2d543d20SAndroid Build Coastguard Worker
39*2d543d20SAndroid Build Coastguard Worker /* Only expect one line "(stdin)= x.." so read and find first space */
40*2d543d20SAndroid Build Coastguard Worker while (fgets(files_digest, sizeof(files_digest) - 1, fp) != NULL)
41*2d543d20SAndroid Build Coastguard Worker ;
42*2d543d20SAndroid Build Coastguard Worker
43*2d543d20SAndroid Build Coastguard Worker files_ptr = strstr(files_digest, " ");
44*2d543d20SAndroid Build Coastguard Worker
45*2d543d20SAndroid Build Coastguard Worker rc = strncmp(selabel_digest, files_ptr + 1, digest_len * 2);
46*2d543d20SAndroid Build Coastguard Worker if (rc) {
47*2d543d20SAndroid Build Coastguard Worker printf("Failed validation:\n\tselabel_digest: %s\n\t"
48*2d543d20SAndroid Build Coastguard Worker "files_digest: %s\n",
49*2d543d20SAndroid Build Coastguard Worker selabel_digest, files_ptr + 1);
50*2d543d20SAndroid Build Coastguard Worker } else {
51*2d543d20SAndroid Build Coastguard Worker printf("Passed validation - digest: %s\n", selabel_digest);
52*2d543d20SAndroid Build Coastguard Worker }
53*2d543d20SAndroid Build Coastguard Worker
54*2d543d20SAndroid Build Coastguard Worker pclose(fp);
55*2d543d20SAndroid Build Coastguard Worker return rc;
56*2d543d20SAndroid Build Coastguard Worker }
57*2d543d20SAndroid Build Coastguard Worker
main(int argc,char ** argv)58*2d543d20SAndroid Build Coastguard Worker int main(int argc, char **argv)
59*2d543d20SAndroid Build Coastguard Worker {
60*2d543d20SAndroid Build Coastguard Worker unsigned int backend = SELABEL_CTX_FILE;
61*2d543d20SAndroid Build Coastguard Worker int rc, opt, validate = 0;
62*2d543d20SAndroid Build Coastguard Worker char *baseonly = NULL, *file = NULL, *digest = (char *)1;
63*2d543d20SAndroid Build Coastguard Worker char **specfiles = NULL;
64*2d543d20SAndroid Build Coastguard Worker unsigned char *sha1_digest = NULL;
65*2d543d20SAndroid Build Coastguard Worker size_t digest_len, i, num_specfiles;
66*2d543d20SAndroid Build Coastguard Worker
67*2d543d20SAndroid Build Coastguard Worker char cmd_buf[4096];
68*2d543d20SAndroid Build Coastguard Worker char *cmd_ptr;
69*2d543d20SAndroid Build Coastguard Worker char *sha1_buf = NULL;
70*2d543d20SAndroid Build Coastguard Worker
71*2d543d20SAndroid Build Coastguard Worker struct selabel_handle *hnd;
72*2d543d20SAndroid Build Coastguard Worker struct selinux_opt selabel_option[] = {
73*2d543d20SAndroid Build Coastguard Worker { SELABEL_OPT_PATH, file },
74*2d543d20SAndroid Build Coastguard Worker { SELABEL_OPT_DIGEST, digest },
75*2d543d20SAndroid Build Coastguard Worker { SELABEL_OPT_BASEONLY, baseonly }
76*2d543d20SAndroid Build Coastguard Worker };
77*2d543d20SAndroid Build Coastguard Worker
78*2d543d20SAndroid Build Coastguard Worker if (argc < 3)
79*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
80*2d543d20SAndroid Build Coastguard Worker
81*2d543d20SAndroid Build Coastguard Worker while ((opt = getopt(argc, argv, "ib:Bvf:")) > 0) {
82*2d543d20SAndroid Build Coastguard Worker switch (opt) {
83*2d543d20SAndroid Build Coastguard Worker case 'b':
84*2d543d20SAndroid Build Coastguard Worker if (!strcasecmp(optarg, "file")) {
85*2d543d20SAndroid Build Coastguard Worker backend = SELABEL_CTX_FILE;
86*2d543d20SAndroid Build Coastguard Worker } else if (!strcmp(optarg, "media")) {
87*2d543d20SAndroid Build Coastguard Worker backend = SELABEL_CTX_MEDIA;
88*2d543d20SAndroid Build Coastguard Worker } else if (!strcmp(optarg, "x")) {
89*2d543d20SAndroid Build Coastguard Worker backend = SELABEL_CTX_X;
90*2d543d20SAndroid Build Coastguard Worker } else if (!strcmp(optarg, "db")) {
91*2d543d20SAndroid Build Coastguard Worker backend = SELABEL_CTX_DB;
92*2d543d20SAndroid Build Coastguard Worker } else if (!strcmp(optarg, "prop")) {
93*2d543d20SAndroid Build Coastguard Worker backend = SELABEL_CTX_ANDROID_PROP;
94*2d543d20SAndroid Build Coastguard Worker } else if (!strcmp(optarg, "service")) {
95*2d543d20SAndroid Build Coastguard Worker backend = SELABEL_CTX_ANDROID_SERVICE;
96*2d543d20SAndroid Build Coastguard Worker } else {
97*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Unknown backend: %s\n",
98*2d543d20SAndroid Build Coastguard Worker optarg);
99*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
100*2d543d20SAndroid Build Coastguard Worker }
101*2d543d20SAndroid Build Coastguard Worker break;
102*2d543d20SAndroid Build Coastguard Worker case 'B':
103*2d543d20SAndroid Build Coastguard Worker baseonly = (char *)1;
104*2d543d20SAndroid Build Coastguard Worker break;
105*2d543d20SAndroid Build Coastguard Worker case 'v':
106*2d543d20SAndroid Build Coastguard Worker validate = 1;
107*2d543d20SAndroid Build Coastguard Worker break;
108*2d543d20SAndroid Build Coastguard Worker case 'i':
109*2d543d20SAndroid Build Coastguard Worker digest = NULL;
110*2d543d20SAndroid Build Coastguard Worker break;
111*2d543d20SAndroid Build Coastguard Worker case 'f':
112*2d543d20SAndroid Build Coastguard Worker file = optarg;
113*2d543d20SAndroid Build Coastguard Worker break;
114*2d543d20SAndroid Build Coastguard Worker default:
115*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
116*2d543d20SAndroid Build Coastguard Worker }
117*2d543d20SAndroid Build Coastguard Worker }
118*2d543d20SAndroid Build Coastguard Worker
119*2d543d20SAndroid Build Coastguard Worker memset(cmd_buf, 0, sizeof(cmd_buf));
120*2d543d20SAndroid Build Coastguard Worker
121*2d543d20SAndroid Build Coastguard Worker selabel_option[0].value = file;
122*2d543d20SAndroid Build Coastguard Worker selabel_option[1].value = digest;
123*2d543d20SAndroid Build Coastguard Worker selabel_option[2].value = baseonly;
124*2d543d20SAndroid Build Coastguard Worker
125*2d543d20SAndroid Build Coastguard Worker hnd = selabel_open(backend, selabel_option, backend == SELABEL_CTX_FILE ? 3 : 2);
126*2d543d20SAndroid Build Coastguard Worker if (!hnd) {
127*2d543d20SAndroid Build Coastguard Worker switch (errno) {
128*2d543d20SAndroid Build Coastguard Worker case EOVERFLOW:
129*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "ERROR Number of specfiles or specfile"
130*2d543d20SAndroid Build Coastguard Worker " buffer caused an overflow.\n");
131*2d543d20SAndroid Build Coastguard Worker break;
132*2d543d20SAndroid Build Coastguard Worker default:
133*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: selabel_open: %s\n",
134*2d543d20SAndroid Build Coastguard Worker strerror(errno));
135*2d543d20SAndroid Build Coastguard Worker }
136*2d543d20SAndroid Build Coastguard Worker return -1;
137*2d543d20SAndroid Build Coastguard Worker }
138*2d543d20SAndroid Build Coastguard Worker
139*2d543d20SAndroid Build Coastguard Worker rc = selabel_digest(hnd, &sha1_digest, &digest_len, &specfiles,
140*2d543d20SAndroid Build Coastguard Worker &num_specfiles);
141*2d543d20SAndroid Build Coastguard Worker
142*2d543d20SAndroid Build Coastguard Worker if (rc) {
143*2d543d20SAndroid Build Coastguard Worker switch (errno) {
144*2d543d20SAndroid Build Coastguard Worker case EINVAL:
145*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "No digest available.\n");
146*2d543d20SAndroid Build Coastguard Worker break;
147*2d543d20SAndroid Build Coastguard Worker default:
148*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "selabel_digest ERROR: %s\n",
149*2d543d20SAndroid Build Coastguard Worker strerror(errno));
150*2d543d20SAndroid Build Coastguard Worker }
151*2d543d20SAndroid Build Coastguard Worker goto err;
152*2d543d20SAndroid Build Coastguard Worker }
153*2d543d20SAndroid Build Coastguard Worker
154*2d543d20SAndroid Build Coastguard Worker sha1_buf = malloc(digest_len * 2 + 1);
155*2d543d20SAndroid Build Coastguard Worker if (!sha1_buf) {
156*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Could not malloc buffer ERROR: %s\n",
157*2d543d20SAndroid Build Coastguard Worker strerror(errno));
158*2d543d20SAndroid Build Coastguard Worker rc = -1;
159*2d543d20SAndroid Build Coastguard Worker goto err;
160*2d543d20SAndroid Build Coastguard Worker }
161*2d543d20SAndroid Build Coastguard Worker
162*2d543d20SAndroid Build Coastguard Worker printf("SHA1 digest: ");
163*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < digest_len; i++)
164*2d543d20SAndroid Build Coastguard Worker sprintf(&(sha1_buf[i * 2]), "%02x", sha1_digest[i]);
165*2d543d20SAndroid Build Coastguard Worker
166*2d543d20SAndroid Build Coastguard Worker printf("%s\n", sha1_buf);
167*2d543d20SAndroid Build Coastguard Worker printf("calculated using the following specfile(s):\n");
168*2d543d20SAndroid Build Coastguard Worker
169*2d543d20SAndroid Build Coastguard Worker if (specfiles) {
170*2d543d20SAndroid Build Coastguard Worker size_t cmd_rem = sizeof(cmd_buf);
171*2d543d20SAndroid Build Coastguard Worker int ret;
172*2d543d20SAndroid Build Coastguard Worker
173*2d543d20SAndroid Build Coastguard Worker if (validate) {
174*2d543d20SAndroid Build Coastguard Worker cmd_ptr = &cmd_buf[0];
175*2d543d20SAndroid Build Coastguard Worker ret = snprintf(cmd_ptr, cmd_rem, "/usr/bin/cat ");
176*2d543d20SAndroid Build Coastguard Worker if (ret < 0 || (size_t)ret >= cmd_rem) {
177*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Could not format validate command\n");
178*2d543d20SAndroid Build Coastguard Worker rc = -1;
179*2d543d20SAndroid Build Coastguard Worker goto err;
180*2d543d20SAndroid Build Coastguard Worker }
181*2d543d20SAndroid Build Coastguard Worker cmd_ptr += ret;
182*2d543d20SAndroid Build Coastguard Worker cmd_rem -= ret;
183*2d543d20SAndroid Build Coastguard Worker }
184*2d543d20SAndroid Build Coastguard Worker
185*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < num_specfiles; i++) {
186*2d543d20SAndroid Build Coastguard Worker if (validate) {
187*2d543d20SAndroid Build Coastguard Worker ret = snprintf(cmd_ptr, cmd_rem, "%s ", specfiles[i]);
188*2d543d20SAndroid Build Coastguard Worker if (ret < 0 || (size_t)ret >= cmd_rem) {
189*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Could not format validate command\n");
190*2d543d20SAndroid Build Coastguard Worker rc = -1;
191*2d543d20SAndroid Build Coastguard Worker goto err;
192*2d543d20SAndroid Build Coastguard Worker }
193*2d543d20SAndroid Build Coastguard Worker cmd_ptr += ret;
194*2d543d20SAndroid Build Coastguard Worker cmd_rem -= ret;
195*2d543d20SAndroid Build Coastguard Worker }
196*2d543d20SAndroid Build Coastguard Worker
197*2d543d20SAndroid Build Coastguard Worker printf("%s\n", specfiles[i]);
198*2d543d20SAndroid Build Coastguard Worker }
199*2d543d20SAndroid Build Coastguard Worker
200*2d543d20SAndroid Build Coastguard Worker if (validate) {
201*2d543d20SAndroid Build Coastguard Worker ret = snprintf(cmd_ptr, cmd_rem, "| /usr/bin/openssl dgst -sha1 -hex");
202*2d543d20SAndroid Build Coastguard Worker if (ret < 0 || (size_t)ret >= cmd_rem) {
203*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Could not format validate command\n");
204*2d543d20SAndroid Build Coastguard Worker rc = -1;
205*2d543d20SAndroid Build Coastguard Worker goto err;
206*2d543d20SAndroid Build Coastguard Worker }
207*2d543d20SAndroid Build Coastguard Worker
208*2d543d20SAndroid Build Coastguard Worker rc = run_check_digest(cmd_buf, sha1_buf, digest_len);
209*2d543d20SAndroid Build Coastguard Worker }
210*2d543d20SAndroid Build Coastguard Worker }
211*2d543d20SAndroid Build Coastguard Worker
212*2d543d20SAndroid Build Coastguard Worker err:
213*2d543d20SAndroid Build Coastguard Worker free(sha1_buf);
214*2d543d20SAndroid Build Coastguard Worker selabel_close(hnd);
215*2d543d20SAndroid Build Coastguard Worker return rc;
216*2d543d20SAndroid Build Coastguard Worker }
217