1#!/usr/bin/python
2#
3# gkhandmake - manually create a recorded snippet
4#
5# gkhandmake path type source outputfile
6#
7import sys
8import os
9import signal
10import errno
11import subprocess
12import plistlib
13
14
15#
16# Usage and fail
17#
18def usage():
19	print >>sys.stderr, "Usage: %s program specfile outputfile" % sys.argv[0]
20	sys.exit(2)
21
22def fail(whatever):
23	print >>sys.stderr, "%s: %s" % (sys.argv[0], whatever)
24	sys.exit(1)
25
26
27#
28# Argument processing
29#
30if len(sys.argv) != 4:
31	usage()
32path=os.path.abspath(sys.argv[1])
33specfile=sys.argv[2]
34outputfile = sys.argv[3]
35type=1	# always execution
36
37
38#
39# If the output file already exists, bail
40#
41if os.path.exists(outputfile):
42	fail("already exists: %s" % outputfile)
43
44
45#
46# We'll let the detached signature live in case we need to inspect it
47#
48sigpath = "/tmp/%s.dsig" % os.path.basename(path.strip('/'))
49
50
51#
52# Generate an adhoc detached signature with the given resource specification
53#
54
55display = subprocess.check_call(["/usr/bin/codesign",
56	"--sign", "-",
57	"--detached", sigpath,
58	"--resource-rules", specfile,
59	path
60])
61
62
63#
64# Now verify it so we can extract the cdhash
65#
66display = subprocess.Popen(["/usr/bin/codesign",
67	"--display", "--verbose=3",
68	"--detached", sigpath,
69	path
70], stderr=subprocess.PIPE)
71(stdout, stderr) = display.communicate()
72
73cdhash = None
74for line in stderr.split('\n'):
75	if line.startswith("CDHash="):
76		cdhash = line[7:]
77		break
78if cdhash is None:
79	fail("no cdhash in generated signature?!")
80
81
82#
83# Pack up a single (detached) signature as a snippet
84# under the given path
85#
86with open(sigpath, "r") as sigfile:
87	sigdata = sigfile.read()
88auth = { }
89sigs = { }
90
91auth[path] = dict(
92	type=type,
93	path=path,
94	status=9,
95	cdhash=cdhash
96)
97
98sigs[path] = dict(
99	type=type,
100	path=path,
101	signature=plistlib.Data(sigdata)
102)
103gkedict = dict(
104	authority = auth,
105	signatures = sigs
106)
107plistlib.writePlist(gkedict, outputfile)
108
109sys.exit(0)
110