;; tinmop: a multiprotocol client ;; Copyright © cage ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. ;; If not, see [[http://www.gnu.org/licenses/][http://www.gnu.org/licenses/]]. (in-package :json-rpc-communication) (defclass gemini-certificates (box) ()) (defmethod yason:encode ((object gemini-certificates) &optional (stream *standard-output*)) (let ((json:*symbol-encoder* #'json:encode-symbol-as-lowercase) (yason:*list-encoder* #'yason:encode-plist) (json:*symbol-key-encoder* #'json:encode-symbol-as-lowercase)) (yason:with-output (stream) (yason:with-array () (loop for certificate in (unbox object) do (yason:encode-array-element certificate)))))) (defun gemini-certificates () (let* ((certificates-rows (sort (db:find-tls-certificates-rows) (lambda (a b) (string< (db:row-cache-key a) (db:row-cache-key b))))) (certificates-with-hash (loop for certificate-row in certificates-rows collect (let* ((cache-key (db:row-cache-key certificate-row))) (multiple-value-bind (pem-file key-file) (gemini-client::tls-cert-find cache-key) (let ((hash (x509:certificate-fingerprint pem-file))) (append (list :hash hash :file pem-file :key-file key-file) certificate-row))))))) (make-instance 'gemini-certificates :contents certificates-with-hash))) (defun gemini-delete-client-certificate (url) (db:cache-invalidate url) t) (defun gemini-delete-tofu-certificate (iri) (let ((host (uri:host (iri:iri-parse iri)))) (db:tofu-delete host))) (defun gemini-import-certificate (uri cert-file key-file) (db-utils:with-ready-database (:connect nil) (if (gemini-parser:gemini-iri-p uri) (let* ((id (to-s (db:cache-put uri +cache-tls-certificate-type+))) (cert-filename (fs:path-last-element cert-file)) (key-filename (fs:path-last-element key-file)) (cache-dir (os-utils:cached-file-path id)) (cert-out-path (strcat cache-dir fs:*directory-sep* cert-filename)) (key-out-path (strcat cache-dir fs:*directory-sep* key-filename))) (fs:make-directory cache-dir) (fs:copy-a-file cert-file cert-out-path :overwrite t) (fs:copy-a-file key-file key-out-path :overwrite t)) (error (format nil (_ "~s is not a valid gemini address") uri))))) (defun gemini-save-certificate-key-password (certificate-path password) (gemini-client:save-cache-certificate-password certificate-path password) t) (defun gemini-url-using-certificate-p (url) (a:when-let* ((certificate-path (gemini-client:fetch-cached-certificate url :if-does-not-exist nil)) (cached-password (gemini-client:retrieve-cached-certificate-password certificate-path))) t))