Commit | Line | Data |
---|---|---|
62e4ed3d A |
1 | #!/usr/bin/python |
2 | # | |
3 | # gkgenerate - produce Gatekeeper explicit allow data | |
4 | # | |
5 | # gkgenerate [--output name] files... | |
6 | # will collect GKE data from all files and write two output files (name.auth and name.sigs) | |
7 | # that are ready to drop into a /var/db for pickup. | |
8 | # | |
9 | import sys | |
10 | import os | |
11 | import signal | |
12 | import errno | |
13 | import subprocess | |
14 | import argparse | |
15 | import plistlib | |
16 | import uuid | |
17 | ||
18 | ||
19 | # | |
20 | # Parameters and constants | |
21 | # | |
22 | authfile = "gke.auth" | |
23 | sigfile = "gke.dsig" | |
24 | ||
25 | ||
26 | # | |
27 | # Usage and fail | |
28 | # | |
29 | def usage(): | |
30 | print >>sys.stderr, "Usage: %s sourcedir" % sys.argv[0] | |
31 | sys.exit(2) | |
32 | ||
33 | def fail(whatever): | |
34 | print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever) | |
35 | sys.exit(1) | |
36 | ||
37 | ||
38 | # | |
39 | # Argument processing | |
40 | # | |
41 | parser = argparse.ArgumentParser() | |
42 | parser.add_argument("--output", default="./gke", help="name of output files") | |
43 | parser.add_argument("--uuid", default=uuid.uuid4(), help="explicitly specify the uuid stamp") | |
44 | parser.add_argument("--empty", action='store_true', help="allow empty output sets") | |
45 | parser.add_argument('source', nargs='+', help='files generated by the gkrecord command') | |
46 | args = parser.parse_args() | |
47 | ||
48 | authfile = args.output + ".auth" | |
49 | sigsfile = args.output + ".sigs" | |
50 | ||
51 | ||
52 | # | |
53 | # Start by collecting authority evidence from the authority records | |
54 | # | |
55 | auth = { } | |
56 | sigs = { } | |
57 | for source in args.source: | |
58 | if source[0] == '+': | |
59 | data = plistlib.readPlist(source[1:]) | |
60 | auth.update(data["authority"]) | |
61 | sigs.update(data["signatures"]) | |
62 | else: | |
63 | data = plistlib.readPlist(source) | |
64 | auth.update(data["authority"]) | |
65 | ||
66 | if not auth and not args.empty: | |
67 | fail("No authority records (nothing to do)") | |
68 | ||
69 | ||
70 | # | |
71 | # Scrub the authority records to remove incriminating evidence | |
72 | # | |
73 | new_auth = { } | |
74 | for rec in auth.values(): | |
75 | u = uuid.uuid4() | |
76 | rec["path"] = "(gke)" | |
77 | del rec["status"] | |
78 | new_auth[str(u)] = rec | |
79 | auth = new_auth | |
80 | ||
81 | ||
82 | # | |
83 | # The authority file is written as-is, as a plist | |
84 | # | |
85 | wrap = dict( | |
86 | authority=auth, | |
87 | uuid=str(args.uuid) | |
88 | ) | |
89 | plistlib.writePlist(wrap, authfile) | |
90 | print "Wrote %d authority record(s) to %s" % (len(auth), authfile) | |
91 | ||
92 | ||
93 | # | |
94 | # The signatures are written as tightly packed signature blobs | |
95 | # | |
96 | sigblobs = open(sigsfile, "w") | |
97 | for sig in sigs: | |
98 | sigdata = sigs[sig] | |
99 | sigblobs.write(sigdata["signature"].data) | |
100 | sigblobs.close() | |
101 | print "Wrote %d signature record(s) to %s" % (len(sigs), sigsfile) |