]>
git.saurik.com Git - apple/security.git/blob - libsecurity_codesigning/gke/gkrecord
3 # gkrecord - record Gatekeeper rejection activity
20 print >>sys
.stderr
, "Usage: %s outputfile" % sys
.argv
[0]
24 print >>sys
.stderr
, "%s: %s" % (sys
.argv
[0], whatever
)
31 if len(sys
.argv
) != 2:
33 outputfile
= sys
.argv
[1]
37 # If the output file already exists, bail
39 if os
.path
.exists(outputfile
):
40 fail("already exists: %s" % outputfile
)
51 fail("Must have root privileges")
55 # Make sure Gatekeeper is disabled
57 subprocess
.check_call(["/usr/sbin/spctl", "--master-disable"])
61 # make sure we have a fresh syspolicyd and get its pid
63 subprocess
.check_call(["/usr/sbin/spctl", "--assess", "--ignore-cache", "/bin/ls"])
65 psax
= subprocess
.check_output("ps ax|grep syspolicyd|grep -v grep", shell
=True).split("\n")
66 if len(psax
) != 2: # [ found_syspolicyd, '' ]
67 fail("Cannot find syspolicyd")
68 spd_pid
= int(psax
[0].split()[0])
69 except subprocess
.CalledProcessError
:
70 fail("Cannot find syspolicyd")
74 # run collector dtrace script until dtrace dies.
75 # recorder_mode arguments are (path, type, label, cdhash, flags)
78 syspolicy$1:::recorder_mode { printf("RECORD;%d;%d", arg1, arg4); }
80 self unsigned char *cdhash;
82 syspolicy$1:::recorder_mode
84 self->cdhash = copyin(arg3, 20);
85 printf(";%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x%02.2x",
86 self->cdhash[0], self->cdhash[1], self->cdhash[2], self->cdhash[3], self->cdhash[4],
87 self->cdhash[5], self->cdhash[6], self->cdhash[7], self->cdhash[8], self->cdhash[9],
88 self->cdhash[10], self->cdhash[11], self->cdhash[12], self->cdhash[13], self->cdhash[14],
89 self->cdhash[15], self->cdhash[16], self->cdhash[17], self->cdhash[18], self->cdhash[19]);
90 printf(";%s\\n", copyinstr(arg0));
93 syspolicy$1:::recorder_mode_adhoc_path
95 printf("SIGNATURE;%d;%s;%s\\n", arg1, copyinstr(arg2), copyinstr(arg0));
98 syspolicy$1:::assess-outcome-unsigned
100 printf("UNSIGNED;%d;%s\\n", arg1, copyinstr(arg0));
103 syspolicy$1:::assess-outcome-broken
105 printf("BROKEN;%d;%d;%s\\n", arg1, arg2, copyinstr(arg0));
109 def sigint(sig
, ctx
):
110 os
.kill(spd_pid
, signal
.SIGINT
)
111 signal
.signal(signal
.SIGINT
, sigint
)
113 (authfd
, authfile
) = tempfile
.mkstemp()
114 dtrace
= subprocess
.Popen(["dtrace", "-qs", "/dev/stdin", str(spd_pid
)], stdin
=subprocess
.PIPE
, stdout
=authfd
, stderr
=subprocess
.PIPE
)
115 print "Exercise the programs to be whitelisted now. Interrupt this script (^C) when you are done."
116 (stdout
, stderr
) = dtrace
.communicate(input=DSCRIPT
)
117 signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
)
119 fail("dtrace failed: %s" % stderr
)
120 os
.lseek(authfd
, os
.SEEK_SET
, 0) # rewind
124 # Collect all the data into dicts
132 file = os
.fdopen(authfd
, "r")
134 (cmd
, s
, args
) = line
.strip().partition(";")
137 # print cmd, "--->", args
139 (type, status
, cdhash
, path
) = args
.split(";", 3)
147 elif cmd
== "SIGNATURE":
148 (type, sigpath
, path
) = args
.split(";", 2)
149 with open(sigpath
, "r") as sigfile
:
150 sigdata
= sigfile
.read()
154 signature
=plistlib
.Data(sigdata
)
156 elif cmd
== "UNSIGNED":
157 (type, path
) = args
.split(";", 1)
158 unsigned
[path
] = dict(
162 elif cmd
== "BROKEN":
163 (type, exception
, path
) = args
.split(";", 2)
164 badsigned
[path
] = dict(
170 # unsigned code that had a good detached signature recorded is okay
177 # Pack them up as a single output (plist) file
183 plistlib
.writePlist(gkedict
, outputfile
)
187 # Report on any problems found
189 for rec
in unsigned
.values():
190 print >>sys
.stderr
, "PROBLEM: unsigned type %d object not whitelisted: %s" % (rec
["type"], rec
["path"])
191 for rec
in badsigned
.values():
192 print >>sys
.stderr
, "PROBLEM: broken code signature; object not whitelisted: %s" % rec
["path"]
198 print "Recorded %d authorization(s), %d signature(s) in %s" % (len(auth
), len(sigs
), outputfile
)