1#import <stdint.h>
2#import <bsm/libbsm.h>
3#import <System/sys/codesign.h>
4#import <sys/errno.h>
5
6#import <err.h>
7#import <stdio.h>
8#import <unistd.h>
9
10int
11get_blob(pid_t pid, int op)
12{
13    uint8_t header[8];
14    unsigned int cnt;
15    int rcent;
16
17    for (cnt = 0; cnt < sizeof(header); cnt++) {
18	rcent = csops(pid, op, header, 1);
19	if (rcent != -1 && errno != ERANGE)
20	    err(1, "errno != ERANGE for short header");
21    }
22
23    rcent = csops(pid, op, header, sizeof(header));
24    if (rcent == -1 && errno == ERANGE) {
25	uint32_t len, bufferlen, bufferlen2;
26
27	memcpy(&len, &header[4], 4);
28	bufferlen = ntohl(len);
29	if (bufferlen > 1024 * 1024)
30	    errx(1, "invalid length on blob from kernel");
31	else if (bufferlen == 0)
32	    errx(1, "bufferlen == 0");
33	else if (bufferlen < 8)
34	    errx(1, "bufferlen <8 0");
35
36	uint8_t buffer[bufferlen + 1];
37
38	rcent = csops(pid, op, buffer, bufferlen - 1);
39	if (rcent != -1 && errno != ERANGE)
40	    errx(1, "csops with full buffer - 1 failed");
41
42	rcent = csops(pid, op, buffer, bufferlen);
43	if (rcent != 0)
44	    errx(1, "csops with full buffer failed");
45
46	memcpy(&len, &buffer[4], 4);
47	bufferlen2 = ntohl(len);
48
49	if (op == CS_OPS_BLOB) {
50		if (bufferlen2 > bufferlen)
51			errx(1, "buffer larger on second try");
52		if (bufferlen2 != bufferlen)
53			warnx("buffer shrunk since codesign can't tell the right size to codesign_allocate");
54	} else {
55		if (bufferlen2 != bufferlen)
56			errx(1, "buffer sizes different");
57	}
58
59	rcent = csops(pid, op, buffer, bufferlen + 1);
60	if (rcent != 0)
61	    errx(1, "csops with full buffer + 1 didn't pass");
62
63	return 0;
64
65    } else if (rcent == 0) {
66        return 0;
67    } else {
68	return 1;
69    }
70}
71
72int
73main(int argc, const char * argv[])
74{
75    uint32_t status;
76    int rcent;
77    pid_t pid;
78
79    pid = getpid();
80
81    if (get_blob(pid, CS_OPS_ENTITLEMENTS_BLOB))
82        errx(1, "failed to get entitlements");
83
84    if (get_blob(0, CS_OPS_ENTITLEMENTS_BLOB))
85        errx(1, "failed to get entitlements");
86
87    if (get_blob(pid, CS_OPS_BLOB))
88        errx(1, "failed to get blob");
89
90    if (get_blob(0, CS_OPS_BLOB))
91        errx(1, "failed to get blob");
92
93    if (get_blob(pid, CS_OPS_IDENTITY))
94        errx(1, "failed to get identity");
95
96    if (get_blob(0, CS_OPS_IDENTITY))
97        errx(1, "failed to get identity");
98
99    rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status) - 1);
100    if (rcent == 0)
101        err(1, "passed when passed in too short status buffer");
102
103    status = htonl(CS_RESTRICT);
104    rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status));
105    if (rcent != 0)
106        errx(1, "failed to mark proc RESTRICTED");
107
108    rcent = csops(pid, CS_OPS_MARKINVALID, NULL, 0);
109    if (rcent != 0)
110        errx(1, "failed to mark proc invalid");
111
112    status = htonl(CS_VALID);
113    rcent = csops(pid, CS_OPS_SET_STATUS, &status, sizeof(status));
114    if (rcent == 0)
115        errx(1, "managed set flags on an INVALID proc");
116
117    if (!get_blob(pid, CS_OPS_ENTITLEMENTS_BLOB))
118        errx(1, "got entitlements while invalid");
119
120    if (!get_blob(pid, CS_OPS_IDENTITY))
121        errx(1, "got identity");
122
123    if (!get_blob(0, CS_OPS_IDENTITY))
124        errx(1, "got identity");
125
126    if (!get_blob(pid, CS_OPS_BLOB))
127        errx(1, "got blob");
128
129    return 0;
130}
131