1 | (in-package asdf-install) |
---|
2 | |
---|
3 | #+(and ignore sbcl) ; Deprecated. |
---|
4 | (define-symbol-macro *sbcl-home* *asdf-install-dirs*) |
---|
5 | |
---|
6 | #+(and ignore sbcl) ; Deprecated. |
---|
7 | (define-symbol-macro *dot-sbcl* *private-asdf-install-dirs*) |
---|
8 | |
---|
9 | #+(or) |
---|
10 | ;; uncalled |
---|
11 | (defun read-until-eof (stream) |
---|
12 | (with-output-to-string (o) |
---|
13 | (copy-stream stream o))) |
---|
14 | |
---|
15 | |
---|
16 | #+(or) |
---|
17 | (defun verify-gpg-signature/string (string file-name) |
---|
18 | (block verify |
---|
19 | (loop |
---|
20 | (restart-case |
---|
21 | (let ((gpg-stream (make-stream-from-gpg-command string file-name)) |
---|
22 | tags) |
---|
23 | (unwind-protect |
---|
24 | (loop for l = (read-line gpg-stream nil nil) |
---|
25 | while l |
---|
26 | do (print l) |
---|
27 | when (> (mismatch l "[GNUPG:]") 6) |
---|
28 | do (destructuring-bind (_ tag &rest data) |
---|
29 | (split-sequence-if (lambda (x) |
---|
30 | (find x '(#\Space #\Tab))) |
---|
31 | l) |
---|
32 | (declare (ignore _)) |
---|
33 | (pushnew (cons (intern (string-upcase tag) :keyword) |
---|
34 | data) tags))) |
---|
35 | (ignore-errors |
---|
36 | (close gpg-stream))) |
---|
37 | ;; test that command returned something |
---|
38 | (unless tags |
---|
39 | (error 'gpg-shell-error)) |
---|
40 | ;; test for obvious key/sig problems |
---|
41 | (let ((errsig (header-value :errsig tags))) |
---|
42 | (and errsig (error 'key-not-found :key-id errsig))) |
---|
43 | (let ((badsig (header-value :badsig tags))) |
---|
44 | (and badsig (error 'key-not-found :key-id badsig))) |
---|
45 | (let* ((good (header-value :goodsig tags)) |
---|
46 | (id (first good)) |
---|
47 | (name (format nil "~{~A~^ ~}" (rest good)))) |
---|
48 | ;; good signature, but perhaps not trusted |
---|
49 | (restart-case |
---|
50 | (let ((trusted? (or (header-pair :trust_ultimate tags) |
---|
51 | (header-pair :trust_fully tags))) |
---|
52 | (in-list? (assoc id *trusted-uids* :test #'equal))) |
---|
53 | (cond ((or trusted? in-list?) |
---|
54 | ;; ok |
---|
55 | ) |
---|
56 | ((not trusted?) |
---|
57 | (error 'key-not-trusted :key-user-name name :key-id id)) |
---|
58 | ((not in-list?) |
---|
59 | (error 'author-not-trusted |
---|
60 | :key-user-name name :key-id id)) |
---|
61 | (t |
---|
62 | (error "Boolean logic gone bad. Run for the hills")))) |
---|
63 | (add-key (&rest rest) |
---|
64 | :report "Add to package supplier list" |
---|
65 | (declare (ignore rest)) |
---|
66 | (pushnew (list id name) *trusted-uids*)))) |
---|
67 | (return-from verify t)) |
---|
68 | #+Ignore |
---|
69 | (install-anyways (&rest rest) |
---|
70 | :report "Don't check GPG signature for this package" |
---|
71 | (declare (ignore rest)) |
---|
72 | (return-from verify t)) |
---|
73 | (retry-gpg-check (&rest args) |
---|
74 | :report "Retry GPG check \(e.g., after downloading the key\)" |
---|
75 | (declare (ignore args)) |
---|
76 | nil))))) |
---|
77 | |
---|
78 | #+(or) |
---|
79 | (defun verify-gpg-signature/url (url file-name) |
---|
80 | (block verify |
---|
81 | (loop |
---|
82 | (restart-case |
---|
83 | (when (verify-gpg-signatures-p url) |
---|
84 | (let ((sig-url (concatenate 'string url ".asc"))) |
---|
85 | (destructuring-bind (response headers stream) |
---|
86 | (url-connection sig-url) |
---|
87 | (unwind-protect |
---|
88 | (flet (#-:digitool |
---|
89 | (read-signature (data stream) |
---|
90 | (read-sequence data stream)) |
---|
91 | #+:digitool |
---|
92 | (read-signature (data stream) |
---|
93 | (multiple-value-bind (reader arg) |
---|
94 | (ccl:stream-reader stream) |
---|
95 | (let ((byte 0)) |
---|
96 | (dotimes (i (length data)) |
---|
97 | (unless (setf byte (funcall reader arg)) |
---|
98 | (error 'download-error :url sig-url |
---|
99 | :response 200)) |
---|
100 | (setf (char data i) (code-char byte))))))) |
---|
101 | (if (= response 200) |
---|
102 | (let ((data (make-string (parse-integer |
---|
103 | (header-value :content-length headers) |
---|
104 | :junk-allowed t)))) |
---|
105 | (read-signature data stream) |
---|
106 | (verify-gpg-signature/string data file-name)) |
---|
107 | (error 'download-error :url sig-url |
---|
108 | :response response))) |
---|
109 | (close stream) |
---|
110 | (return-from verify t))))) |
---|
111 | (install-anyways (&rest rest) |
---|
112 | :report "Don't check GPG signature for this package" |
---|
113 | (declare (ignore rest)) |
---|
114 | (return-from verify t)) |
---|
115 | (retry-gpg-check (&rest args) |
---|
116 | :report "Retry GPG check \(e.g., after fixing the network connection\)" |
---|
117 | (declare (ignore args)) |
---|
118 | nil))))) |
---|
119 | |
---|
120 | |
---|
121 | #+(or :sbcl :cmu :scl) |
---|
122 | (defun make-stream-from-gpg-command (string file-name) |
---|
123 | (#+:sbcl sb-ext:process-output |
---|
124 | #+(or :cmu :scl) ext:process-output |
---|
125 | (#+:sbcl sb-ext:run-program |
---|
126 | #+(or :cmu :scl) ext:run-program |
---|
127 | "gpg" |
---|
128 | (list |
---|
129 | "--status-fd" "1" "--verify" "-" |
---|
130 | (namestring file-name)) |
---|
131 | :output :stream |
---|
132 | :error nil |
---|
133 | #+sbcl :search #+sbcl t |
---|
134 | :input (make-string-input-stream string) |
---|
135 | :wait t))) |
---|
136 | |
---|
137 | #+(and :lispworks (not :win32)) |
---|
138 | (defun make-stream-from-gpg-command (string file-name) |
---|
139 | ;; kludge - we can't separate the in and out streams |
---|
140 | (let ((stream (sys:open-pipe (format nil "echo '~A' | gpg --status-fd 1 --verify - ~A" |
---|
141 | string |
---|
142 | (namestring file-name))))) |
---|
143 | stream)) |
---|
144 | |
---|
145 | |
---|
146 | #+(and :lispworks :win32) |
---|
147 | (defun make-stream-from-gpg-command (string file-name) |
---|
148 | (sys:open-pipe (format nil "gpg --status-fd 1 --verify \"~A\" \"~A\"" |
---|
149 | (make-temp-sig file-name string) |
---|
150 | (namestring file-name)))) |
---|
151 | |
---|
152 | #+(and :clisp (not (or :win32 :cygwin))) |
---|
153 | (defun make-stream-from-gpg-command (string file-name) |
---|
154 | (let ((stream |
---|
155 | (ext:run-shell-command (format nil "echo '~A' | gpg --status-fd 1 --verify - ~A" |
---|
156 | string |
---|
157 | (namestring file-name)) |
---|
158 | :output :stream |
---|
159 | :wait nil))) |
---|
160 | stream)) |
---|
161 | |
---|
162 | #+(and :clisp (or :win32 :cygwin)) |
---|
163 | (defun make-stream-from-gpg-command (string file-name) |
---|
164 | (ext:run-shell-command (format nil "gpg --status-fd 1 --verify \"~A\" \"~A\"" |
---|
165 | (make-temp-sig file-name string) |
---|
166 | (namestring file-name)) |
---|
167 | :output :stream |
---|
168 | :wait nil)) |
---|
169 | |
---|
170 | #+:allegro |
---|
171 | (defun make-stream-from-gpg-command (string file-name) |
---|
172 | (multiple-value-bind (in-stream out-stream) |
---|
173 | (excl:run-shell-command |
---|
174 | #-:mswindows |
---|
175 | (concatenate 'vector |
---|
176 | #("gpg" "gpg" "--status-fd" "1" "--verify" "-") |
---|
177 | (make-sequence 'vector 1 |
---|
178 | :initial-element (namestring file-name))) |
---|
179 | #+:mswindows |
---|
180 | (format nil "gpg --status-fd 1 --verify - \"~A\"" (namestring file-name)) |
---|
181 | :input :stream |
---|
182 | :output :stream |
---|
183 | :separate-streams t |
---|
184 | :wait nil) |
---|
185 | (write-string string in-stream) |
---|
186 | (finish-output in-stream) |
---|
187 | (close in-stream) |
---|
188 | out-stream)) |
---|
189 | |
---|
190 | #+:openmcl |
---|
191 | (defun make-stream-from-gpg-command (string file-name) |
---|
192 | (let ((proc (ccl:run-program "gpg" (list "--status-fd" "1" "--verify" "-" (namestring file-name)) |
---|
193 | :input :stream |
---|
194 | :output :stream |
---|
195 | :wait nil))) |
---|
196 | (write-string string (ccl:external-process-input-stream proc)) |
---|
197 | (close (ccl:external-process-input-stream proc)) |
---|
198 | (ccl:external-process-output-stream proc))) |
---|
199 | |
---|
200 | #+:digitool |
---|
201 | (defun make-stream-from-gpg-command (string file-name) |
---|
202 | (make-instance 'popen-input-stream |
---|
203 | :command (format nil "echo '~A' | gpg --status-fd 1 --verify - '~A'" |
---|
204 | string |
---|
205 | (system-namestring file-name)))) |
---|
206 | |
---|
207 | #+(or) |
---|
208 | (defun make-temp-sig (file-name content) |
---|
209 | (let ((name (format nil "~A.asc" (namestring (truename file-name))))) |
---|
210 | (with-open-file (out name |
---|
211 | :direction :output |
---|
212 | :if-exists :supersede) |
---|
213 | (write-string content out)) |
---|
214 | (pushnew name *temporary-files*) |
---|
215 | name)) |
---|
216 | |
---|