]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_codesigning/gke/gkgenerate
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_codesigning / gke / gkgenerate
diff --git a/Security/libsecurity_codesigning/gke/gkgenerate b/Security/libsecurity_codesigning/gke/gkgenerate
new file mode 100755 (executable)
index 0000000..127d9b0
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+#
+# gkgenerate - produce Gatekeeper explicit allow data
+#
+# gkgenerate [--output name] files...
+#      will collect GKE data from all files and write two output files (name.auth and name.sigs)
+#      that are ready to drop into a /var/db for pickup.
+#
+import sys
+import os
+import signal
+import errno
+import subprocess
+import argparse
+import plistlib
+import uuid
+
+
+#
+# Parameters and constants
+#
+authfile = "gke.auth"
+sigfile = "gke.dsig"
+
+#
+# Usage and fail
+#
+def usage():
+       print >>sys.stderr, "Usage: %s sourcedir" % sys.argv[0]
+       sys.exit(2)
+
+def fail(whatever):
+       print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever)
+       sys.exit(1)
+
+
+#
+# Argument processing
+#
+parser = argparse.ArgumentParser()
+parser.add_argument("--output", default="./gke", help="name of output files")
+parser.add_argument("--uuid", default=uuid.uuid4(), help="explicitly specify the uuid stamp")
+parser.add_argument("--empty", action='store_true', help="allow empty output sets")
+parser.add_argument('source', nargs='+', help='files generated by the gkrecord command')
+args = parser.parse_args()
+
+authfile = args.output + ".auth"
+sigsfile = args.output + ".sigs"
+
+
+#
+# Augment a snippet record
+#
+def augment(data):
+       for auth in data.authority.values():
+               if auth.path in data.signatures:
+                       signature = data.signatures[auth.path].signature.data
+                       unpack = subprocess.Popen(["/usr/local/bin/gkunpack"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                       (stdout, stderr) = unpack.communicate(input=signature)
+                       if stderr:
+                               fail("signature unpack failed for %s" % auth.path)
+                       auth.screen = stdout.rstrip();
+
+
+#
+# Start by collecting authority evidence from the authority records
+#
+auth = { }
+sigs = { }
+for source in args.source:
+       if source[0] == '+':
+               data = plistlib.readPlist(source[1:])
+               augment(data)
+               auth.update(data["authority"])
+               sigs.update(data["signatures"])
+       else:
+               data = plistlib.readPlist(source)
+               augment(data)
+               auth.update(data["authority"])
+
+if not auth and not args.empty:
+       fail("No authority records (nothing to do)")
+
+
+#
+# Scrub the authority records to remove incriminating evidence
+#
+new_auth = { }
+for rec in auth.values():
+       u = uuid.uuid4()
+       rec["path"] = "(gke)"
+       del rec["status"]
+       new_auth[str(u)] = rec
+auth = new_auth
+
+
+#
+# The authority file is written as-is, as a plist
+#
+wrap = dict(
+       authority=auth,
+       uuid=str(args.uuid)
+)
+plistlib.writePlist(wrap, authfile)
+print "Wrote %d authority record(s) to %s" % (len(auth), authfile)
+
+
+#
+# The signatures are written as tightly packed signature blobs
+#
+sigblobs = open(sigsfile, "w")
+for sig in sigs:
+       sigdata = sigs[sig]
+       sigblobs.write(sigdata["signature"].data)
+sigblobs.close()
+print "Wrote %d signature record(s) to %s" % (len(sigs), sigsfile)