]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/gke/gkgenerate
Security-57337.50.23.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / gke / gkgenerate
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 # Usage and fail
27 #
28 def usage():
29 print >>sys.stderr, "Usage: %s sourcedir" % sys.argv[0]
30 sys.exit(2)
31
32 def fail(whatever):
33 print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever)
34 sys.exit(1)
35
36
37 #
38 # Argument processing
39 #
40 parser = argparse.ArgumentParser()
41 parser.add_argument("--output", default="./gke", help="name of output files")
42 parser.add_argument("--uuid", default=uuid.uuid4(), help="explicitly specify the uuid stamp")
43 parser.add_argument("--empty", action='store_true', help="allow empty output sets")
44 parser.add_argument('source', nargs='+', help='files generated by the gkrecord command')
45 args = parser.parse_args()
46
47 authfile = args.output + ".auth"
48 sigsfile = args.output + ".sigs"
49
50
51 #
52 # Augment a snippet record
53 #
54 def augment(data):
55 for auth in data.authority.values():
56 if auth.path in data.signatures:
57 signature = data.signatures[auth.path].signature.data
58 unpack = subprocess.Popen(["/usr/local/bin/gkunpack"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
59 (stdout, stderr) = unpack.communicate(input=signature)
60 if stderr:
61 fail("signature unpack failed for %s" % auth.path)
62 auth.screen = stdout.rstrip();
63
64
65 #
66 # Start by collecting authority evidence from the authority records
67 #
68 auth = { }
69 sigs = { }
70 for source in args.source:
71 if source[0] == '+':
72 data = plistlib.readPlist(source[1:])
73 augment(data)
74 auth.update(data["authority"])
75 sigs.update(data["signatures"])
76 else:
77 data = plistlib.readPlist(source)
78 augment(data)
79 auth.update(data["authority"])
80
81 if not auth and not args.empty:
82 fail("No authority records (nothing to do)")
83
84
85 #
86 # Scrub the authority records to remove incriminating evidence
87 #
88 new_auth = { }
89 for rec in auth.values():
90 u = uuid.uuid4()
91 rec["path"] = "(gke)"
92 del rec["status"]
93 new_auth[str(u)] = rec
94 auth = new_auth
95
96
97 #
98 # The authority file is written as-is, as a plist
99 #
100 wrap = dict(
101 authority=auth,
102 uuid=str(args.uuid)
103 )
104 plistlib.writePlist(wrap, authfile)
105 print "Wrote %d authority record(s) to %s" % (len(auth), authfile)
106
107
108 #
109 # The signatures are written as tightly packed signature blobs
110 #
111 sigblobs = open(sigsfile, "w")
112 for sig in sigs:
113 sigdata = sigs[sig]
114 sigblobs.write(sigdata["signature"].data)
115 sigblobs.close()
116 print "Wrote %d signature record(s) to %s" % (len(sigs), sigsfile)