| 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 | |
|---|