diff options
| author | Ken Manheimer | 2010-12-08 14:57:06 -0500 |
|---|---|---|
| committer | Ken Manheimer | 2010-12-08 14:57:06 -0500 |
| commit | ff3e8c8e20fab5078b4e3a8a4eacc026eea71b6d (patch) | |
| tree | e376fc230ff78e8468ee9c124dd9476c1d855b53 | |
| parent | 7484c933aab704222d923b56ce134d2728ec2da9 (diff) | |
| download | emacs-ff3e8c8e20fab5078b4e3a8a4eacc026eea71b6d.tar.gz emacs-ff3e8c8e20fab5078b4e3a8a4eacc026eea71b6d.zip | |
partial checking with substantial progress towards epg passphrase
callback arrangements. several reasons to drop the special provisions:
- gpg v1 is required for passphrase callback operation - so allout
passphrase hinting and verification requires that
- exposes passphrase to emacs code, which is much much less secure than
sticking with gpg v2 and leaving all passphrase handling in gpg
- leaving all passphrase handling to gpg removes a lot of complexity from
allout code
- gpg v2 connection to gpg-agent requires no user provisions, so is simpler
and provides some convenience that makes up for the lack of hinting and
verification
this checkin includes a partially developed version of
allout-epg-passphrase-callback-function, with hinting and ready to
implement the passphrase verification. but there's a lot to go there, and
in working through the twisty flow to adjust the verifier and hint string,
etc. not worth it, considering the above trade-offs.
| -rw-r--r-- | lisp/allout.el | 418 |
1 files changed, 204 insertions, 214 deletions
diff --git a/lisp/allout.el b/lisp/allout.el index 50c2bb194a1..7f600eef899 100644 --- a/lisp/allout.el +++ b/lisp/allout.el | |||
| @@ -43,9 +43,8 @@ | |||
| 43 | ;; - Symmetric-key and key-pair topic encryption, plus symmetric passphrase | 43 | ;; - Symmetric-key and key-pair topic encryption, plus symmetric passphrase |
| 44 | ;; mnemonic support, with verification against an established passphrase | 44 | ;; mnemonic support, with verification against an established passphrase |
| 45 | ;; (using a stashed encrypted dummy string) and user-supplied hint | 45 | ;; (using a stashed encrypted dummy string) and user-supplied hint |
| 46 | ;; maintenance. (See allout-toggle-current-subtree-encryption docstring. | 46 | ;; maintenance. Encryption is via the Emacs 'epg' library. See |
| 47 | ;; Currently only GnuPG encryption is supported | 47 | ;; allout-toggle-current-subtree-encryption docstring. |
| 48 | ;;PGG and integration with gpg-agent is not yet implemented.) | ||
| 49 | ;; - Automatic topic-number maintenance | 48 | ;; - Automatic topic-number maintenance |
| 50 | ;; - "Hot-spot" operation, for single-keystroke maneuvering and | 49 | ;; - "Hot-spot" operation, for single-keystroke maneuvering and |
| 51 | ;; exposure control (see the allout-mode docstring) | 50 | ;; exposure control (see the allout-mode docstring) |
| @@ -84,11 +83,9 @@ | |||
| 84 | ;;;_* Dependency autoloads | 83 | ;;;_* Dependency autoloads |
| 85 | (require 'overlay) | 84 | (require 'overlay) |
| 86 | (eval-when-compile | 85 | (eval-when-compile |
| 87 | ;; Most of the requires here are for stuff covered by autoloads. | 86 | ;; Most of the requires here are for stuff covered by autoloads, which |
| 88 | ;; Since just byte-compiling doesn't trigger autoloads, so that | 87 | ;; byte-compiling doesn't trigger. |
| 89 | ;; "function not found" warnings would occur without these requires. | 88 | (require 'epa) |
| 90 | (require 'pgg) | ||
| 91 | (require 'pgg-gpg) | ||
| 92 | (require 'overlay) | 89 | (require 'overlay) |
| 93 | ;; `cl' is required for `assert'. `assert' is not covered by a standard | 90 | ;; `cl' is required for `assert'. `assert' is not covered by a standard |
| 94 | ;; autoload, but it is a macro, so that eval-when-compile is sufficient | 91 | ;; autoload, but it is a macro, so that eval-when-compile is sufficient |
| @@ -1536,6 +1533,12 @@ wrapped within allout's automatic fill-prefix setting.") | |||
| 1536 | "Horrible hack used to prevent invalid multiple triggering of outline | 1533 | "Horrible hack used to prevent invalid multiple triggering of outline |
| 1537 | mode from prop-line file-var activation. Used by `allout-mode' function | 1534 | mode from prop-line file-var activation. Used by `allout-mode' function |
| 1538 | to track repeats.") | 1535 | to track repeats.") |
| 1536 | ;;;_ = allout-epg-protocol | ||
| 1537 | (defvar allout-epg-protocol 'OpenPGP | ||
| 1538 | "*The default protocol. | ||
| 1539 | The value can be either 'OpenPGP or 'CMS. | ||
| 1540 | |||
| 1541 | You should bind this variable with `let', but do not set it globally.") | ||
| 1539 | ;;;_ = allout-passphrase-verifier-string | 1542 | ;;;_ = allout-passphrase-verifier-string |
| 1540 | (defvar allout-passphrase-verifier-string nil | 1543 | (defvar allout-passphrase-verifier-string nil |
| 1541 | "Setting used to test solicited encryption passphrases against the one | 1544 | "Setting used to test solicited encryption passphrases against the one |
| @@ -1596,15 +1599,15 @@ substition is used against the regexp matches, a la `replace-match'.") | |||
| 1596 | (defvar allout-encryption-ciphertext-rejection-regexps nil | 1599 | (defvar allout-encryption-ciphertext-rejection-regexps nil |
| 1597 | "Variable for regexps matching plaintext to remove before encryption. | 1600 | "Variable for regexps matching plaintext to remove before encryption. |
| 1598 | 1601 | ||
| 1599 | This is for the sake of redoing encryption in cases where the ciphertext | 1602 | This is used to detect strings in encryption results that would |
| 1600 | incidentally contains strings that would disrupt mode operation -- | 1603 | register as allout mode structural elements, for exmple, as a |
| 1601 | for example, a line that happens to look like an allout-mode topic prefix. | 1604 | topic prefix. |
| 1602 | 1605 | ||
| 1603 | Entries must be symbols that are bound to the desired regexp values. | 1606 | Entries must be symbols that are bound to the desired regexp values. |
| 1604 | 1607 | ||
| 1605 | The encryption will be retried up to | 1608 | Encryptions that result in matches will be retried, up to |
| 1606 | `allout-encryption-ciphertext-rejection-limit' times, after which an error | 1609 | `allout-encryption-ciphertext-rejection-limit' times, after which |
| 1607 | is raised.") | 1610 | an error is raised.") |
| 1608 | 1611 | ||
| 1609 | (make-variable-buffer-local 'allout-encryption-ciphertext-rejection-regexps) | 1612 | (make-variable-buffer-local 'allout-encryption-ciphertext-rejection-regexps) |
| 1610 | ;;;_ = allout-encryption-ciphertext-rejection-ceiling | 1613 | ;;;_ = allout-encryption-ciphertext-rejection-ceiling |
| @@ -6033,9 +6036,6 @@ encrypted. If you want to encrypt the contents of a top-level topic, use | |||
| 6033 | The encryption passphrase is solicited if not currently available in the | 6036 | The encryption passphrase is solicited if not currently available in the |
| 6034 | passphrase cache from a recent encryption action. | 6037 | passphrase cache from a recent encryption action. |
| 6035 | 6038 | ||
| 6036 | ;;PGG The solicited passphrase is retained for reuse in a cache, if enabled. See | ||
| 6037 | ;;PGG `pgg-cache-passphrase' and `pgg-passphrase-cache-expiry' for details. | ||
| 6038 | |||
| 6039 | Symmetric Passphrase Hinting and Verification | 6039 | Symmetric Passphrase Hinting and Verification |
| 6040 | 6040 | ||
| 6041 | If the file previously had no associated passphrase, or had a different | 6041 | If the file previously had no associated passphrase, or had a different |
| @@ -6115,6 +6115,7 @@ See `allout-toggle-current-subtree-encryption' for more details." | |||
| 6115 | (if was-encrypted "de" "en")) | 6115 | (if was-encrypted "de" "en")) |
| 6116 | nil)) | 6116 | nil)) |
| 6117 | ;; Assess key parameters: | 6117 | ;; Assess key parameters: |
| 6118 | ;;PGG rework key-info! | ||
| 6118 | (key-info (or | 6119 | (key-info (or |
| 6119 | ;; detect the type by which it is already encrypted | 6120 | ;; detect the type by which it is already encrypted |
| 6120 | (and was-encrypted | 6121 | (and was-encrypted |
| @@ -6152,7 +6153,6 @@ See `allout-toggle-current-subtree-encryption' for more details." | |||
| 6152 | (allout-encrypt-string subject-text was-encrypted | 6153 | (allout-encrypt-string subject-text was-encrypted |
| 6153 | (current-buffer) | 6154 | (current-buffer) |
| 6154 | for-key-type for-key-identity | 6155 | for-key-type for-key-identity |
| 6155 | ;;PGG fetch-pass | ||
| 6156 | )) | 6156 | )) |
| 6157 | 6157 | ||
| 6158 | ;; Replace the subtree with the processed product. | 6158 | ;; Replace the subtree with the processed product. |
| @@ -6184,65 +6184,29 @@ See `allout-toggle-current-subtree-encryption' for more details." | |||
| 6184 | (insert "*")))) | 6184 | (insert "*")))) |
| 6185 | (run-hook-with-args 'allout-structure-added-hook | 6185 | (run-hook-with-args 'allout-structure-added-hook |
| 6186 | bullet-pos subtree-end)))) | 6186 | bullet-pos subtree-end)))) |
| 6187 | ;;;_ > allout-encrypt-string (text decrypt allout-buffer key-type for-key | 6187 | ;;;_ > allout-encrypt-string (text decrypt allout-buffer) |
| 6188 | ;;; ;;PGG fetch-pass | 6188 | (defun allout-encrypt-string (text decrypt allout-buffer &optional rejected) |
| 6189 | ;;; &optional retried verifying | ||
| 6190 | ;;; passphrase) | ||
| 6191 | (defun allout-encrypt-string (text decrypt allout-buffer key-type for-key | ||
| 6192 | ;;PGG fetch-pass | ||
| 6193 | &optional retried rejected | ||
| 6194 | verifying passphrase) | ||
| 6195 | "Encrypt or decrypt message TEXT. | 6189 | "Encrypt or decrypt message TEXT. |
| 6196 | 6190 | ||
| 6197 | If DECRYPT is true (default false), then decrypt instead of encrypt. | 6191 | Returns the resulting string, or nil if the transformation fails. |
| 6198 | |||
| 6199 | KEY-TYPE, either `symmetric' or `keypair', specifies which type | ||
| 6200 | of cypher to use. | ||
| 6201 | 6192 | ||
| 6202 | FOR-KEY is human readable identification of the first of the user's | 6193 | If DECRYPT is true (default false), then decrypt instead of encrypt. |
| 6203 | eligible secret keys a keypair decryption targets, or else nil. | ||
| 6204 | |||
| 6205 | ;;PGG FETCH-PASS (default false) forces fresh prompting for the passphrase. | ||
| 6206 | |||
| 6207 | Optional RETRIED is for internal use -- conveys the number of failed keys | ||
| 6208 | that have been solicited in sequence leading to this current call. | ||
| 6209 | 6194 | ||
| 6210 | Optional PASSPHRASE enables explicit delivery of the decryption passphrase, | 6195 | ALLOUT-BUFFER identifies the buffer containing the text. |
| 6211 | for verification purposes. | ||
| 6212 | 6196 | ||
| 6213 | Optional REJECTED is for internal use -- conveys the number of | 6197 | Optional REJECTED is for internal use -- conveys the number of |
| 6214 | rejections due to matches against | 6198 | rejections due to matches against |
| 6215 | `allout-encryption-ciphertext-rejection-regexps', as limited by | 6199 | `allout-encryption-ciphertext-rejection-regexps', as limited by |
| 6216 | `allout-encryption-ciphertext-rejection-ceiling'. | 6200 | `allout-encryption-ciphertext-rejection-ceiling'. |
| 6201 | " | ||
| 6217 | 6202 | ||
| 6218 | Returns the resulting string, or nil if the transformation fails." | 6203 | (require 'epg) |
| 6219 | |||
| 6220 | (require 'epa) | ||
| 6221 | (require 'pgg) | ||
| 6222 | 6204 | ||
| 6223 | (let* ((epg-context (epg-make-context epa-protocol t)) | 6205 | (let* ((epg-context (epg-make-context epa-protocol t)) |
| 6224 | ;;PGG (scheme (upcase | ||
| 6225 | ;;PGG (format "%s" (or pgg-scheme pgg-default-scheme "GPG")))) | ||
| 6226 | (for-key (and (equal key-type 'keypair) | ||
| 6227 | (or for-key | ||
| 6228 | (split-string (read-string | ||
| 6229 | (format "%s message recipients: " | ||
| 6230 | epa-protocol)) | ||
| 6231 | "[ \t,]+")))) | ||
| 6232 | (target-prompt-id (if (equal key-type 'keypair) | ||
| 6233 | (if (= (length for-key) 1) | ||
| 6234 | (car for-key) for-key) | ||
| 6235 | (buffer-name allout-buffer))) | ||
| 6236 | ;;PGG (target-cache-id (format "%s-%s" | ||
| 6237 | ;;PGG key-type | ||
| 6238 | ;;PGG (if (equal key-type 'keypair) | ||
| 6239 | ;;PGG target-prompt-id | ||
| 6240 | ;;PGG (or (buffer-file-name allout-buffer) | ||
| 6241 | ;;PGG target-prompt-id)))) | ||
| 6242 | (encoding (with-current-buffer allout-buffer | 6206 | (encoding (with-current-buffer allout-buffer |
| 6243 | buffer-file-coding-system)) | 6207 | buffer-file-coding-system)) |
| 6244 | (multibyte (with-current-buffer allout-buffer | 6208 | (multibyte (with-current-buffer allout-buffer |
| 6245 | enable-multibyte-characters)) | 6209 | enable-multibyte-characters)) |
| 6246 | (strip-plaintext-regexps | 6210 | (strip-plaintext-regexps |
| 6247 | (if (not decrypt) | 6211 | (if (not decrypt) |
| 6248 | (allout-get-configvar-values | 6212 | (allout-get-configvar-values |
| @@ -6254,160 +6218,186 @@ Returns the resulting string, or nil if the transformation fails." | |||
| 6254 | (rejected (or rejected 0)) | 6218 | (rejected (or rejected 0)) |
| 6255 | (rejections-left (- allout-encryption-ciphertext-rejection-ceiling | 6219 | (rejections-left (- allout-encryption-ciphertext-rejection-ceiling |
| 6256 | rejected)) | 6220 | rejected)) |
| 6257 | result-text status | 6221 | massaged-text result-text |
| 6258 | ) | 6222 | ) |
| 6259 | 6223 | ||
| 6260 | ;;PGG (if (and fetch-pass (not passphrase)) | 6224 | ;; Massage the subject text for encoding and filtering. |
| 6261 | ;;PGG ;; Force later fetch by evicting passphrase from the cache. | 6225 | (with-temp-buffer |
| 6262 | ;;PGG (pgg-remove-passphrase-from-cache target-cache-id t)) | 6226 | (insert text) |
| 6263 | 6227 | ;; convey the text characteristics of the original buffer: | |
| 6264 | (catch 'encryption-failed | 6228 | (allout-set-buffer-multibyte multibyte) |
| 6265 | 6229 | (when encoding | |
| 6266 | ;; We handle only symmetric-key passphrase caching. | 6230 | (set-buffer-file-coding-system encoding) |
| 6267 | (if (and (not passphrase) | 6231 | (if (not decrypt) |
| 6268 | (not (equal key-type 'keypair))) | 6232 | (encode-coding-region (point-min) (point-max) encoding))) |
| 6269 | (setq passphrase (allout-obtain-passphrase for-key | 6233 | |
| 6270 | ;;PGG target-cache-id | 6234 | ;; remove sanitization regexps matches before encrypting: |
| 6271 | target-prompt-id | 6235 | (when (and strip-plaintext-regexps (not decrypt)) |
| 6272 | key-type | 6236 | (dolist (re strip-plaintext-regexps) |
| 6273 | allout-buffer | 6237 | (let ((re (if (listp re) (car re) re)) |
| 6274 | retried | 6238 | (replacement (if (listp re) (cadr re) ""))) |
| 6275 | ;;PGG fetch-pass | 6239 | (goto-char (point-min)) |
| 6276 | ))) | 6240 | (save-match-data |
| 6277 | 6241 | (while (re-search-forward re nil t) | |
| 6278 | (with-temp-buffer | 6242 | (replace-match replacement nil nil)))))) |
| 6279 | 6243 | (setq massaged-text (buffer-substring-no-properties (point-min) | |
| 6280 | (insert text) | 6244 | (point-max)))) |
| 6281 | 6245 | (setq result-text | |
| 6282 | ;; convey the text characteristics of the original buffer: | 6246 | |
| 6283 | (allout-set-buffer-multibyte multibyte) | 6247 | (if decrypt |
| 6284 | (when encoding | 6248 | |
| 6285 | (set-buffer-file-coding-system encoding) | 6249 | (epg-decrypt-string epg-context |
| 6286 | (if (not decrypt) | 6250 | (encode-coding-string massaged-text |
| 6287 | (encode-coding-region (point-min) (point-max) encoding))) | 6251 | (or encoding 'utf-8))) |
| 6288 | 6252 | ||
| 6289 | (when (and strip-plaintext-regexps (not decrypt)) | 6253 | (if (equal key-type 'symmetric) |
| 6290 | (dolist (re strip-plaintext-regexps) | 6254 | ;; establish the passphrase callback. it will only be used |
| 6291 | (let ((re (if (listp re) (car re) re)) | 6255 | ;; with gpgv1, but then it will handle hinting and verification. |
| 6292 | (replacement (if (listp re) (cadr re) ""))) | 6256 | (allout-set-epg-passphrase-callback epg-context allout-buffer)) |
| 6293 | (goto-char (point-min)) | 6257 | |
| 6294 | (save-match-data | 6258 | (epg-encrypt-string epg-context |
| 6295 | (while (re-search-forward re nil t) | 6259 | (encode-coding-string massaged-text |
| 6296 | (replace-match replacement nil nil)))))) | 6260 | (or encoding 'utf-8)) |
| 6297 | 6261 | nil))) | |
| 6298 | (cond | 6262 | |
| 6299 | 6263 | ;; validate result -- non-empty | |
| 6300 | ;; symmetric: | 6264 | (if (not result-text) |
| 6301 | ((equal key-type 'symmetric) | 6265 | (error "%scryption failed." (if decrypt "De" "En")) |
| 6302 | (setq status | 6266 | |
| 6303 | (if decrypt | 6267 | ;; Retry (within limit) if ciphertext contains rejections: |
| 6304 | 6268 | ((and (not decrypt) | |
| 6305 | (pgg-decrypt (point-min) (point-max) passphrase) | 6269 | ;; Check for disqualification of this ciphertext: |
| 6306 | 6270 | (let ((regexps reject-ciphertext-regexps) | |
| 6307 | (pgg-encrypt-symmetric (point-min) (point-max) | 6271 | reject-it) |
| 6308 | passphrase))) | 6272 | (while (and regexps (not reject-it)) |
| 6309 | 6273 | (setq reject-it (string-match (car regexps) result-text)) | |
| 6310 | (if status | 6274 | (pop regexps)) |
| 6311 | (pgg-situate-output (point-min) (point-max)) | 6275 | reject-it)) |
| 6312 | ;; failed -- handle passphrase caching | 6276 | (setq rejections-left (1- rejections-left)) |
| 6313 | (if verifying | 6277 | (if (<= rejections-left 0) |
| 6314 | (throw 'encryption-failed nil) | 6278 | (error (concat "Ciphertext rejected too many times" |
| 6315 | ;;PGG (pgg-remove-passphrase-from-cache target-cache-id t) | 6279 | " (%s), per `%s'") |
| 6316 | (error "Symmetric-cipher %scryption failed -- %s" | 6280 | allout-encryption-ciphertext-rejection-ceiling |
| 6317 | (if decrypt "de" "en") | 6281 | 'allout-encryption-ciphertext-rejection-regexps) |
| 6318 | "try again with different passphrase")))) | 6282 | ;; try again: |
| 6319 | 6283 | ;; XXX alas, we depend on external caching for the passphrase. | |
| 6320 | ;; encrypt `keypair': | 6284 | (allout-encrypt-string text decrypt allout-buffer |
| 6321 | ((not decrypt) | 6285 | (1+ rejected)))) |
| 6322 | 6286 | ||
| 6323 | (setq status | 6287 | ;; Barf if encryption yields extraordinary control chars: |
| 6324 | 6288 | ((and (not decrypt) | |
| 6325 | (pgg-encrypt for-key | 6289 | (string-match "[\C-a\C-k\C-o-\C-z\C-@]" |
| 6326 | nil (point-min) (point-max) passphrase)) | 6290 | result-text)) |
| 6327 | 6291 | (error (concat "Encryption produced non-armored text, which" | |
| 6328 | (if status | 6292 | "conflicts with allout mode -- reconfigure!"))) |
| 6329 | (pgg-situate-output (point-min) (point-max)) | 6293 | |
| 6330 | (error ;;PGG (pgg-remove-passphrase-from-cache target-cache-id t) | 6294 | (t result-text) |
| 6331 | (error "encryption failed")))) | 6295 | ) |
| 6332 | |||
| 6333 | ;; decrypt `keypair': | ||
| 6334 | (t | ||
| 6335 | |||
| 6336 | (setq status | ||
| 6337 | (pgg-decrypt (point-min) (point-max) passphrase)) | ||
| 6338 | |||
| 6339 | (if status | ||
| 6340 | (pgg-situate-output (point-min) (point-max)) | ||
| 6341 | (error ;;PGG (pgg-remove-passphrase-from-cache target-cache-id t) | ||
| 6342 | (error "decryption failed"))))) | ||
| 6343 | |||
| 6344 | (setq result-text | ||
| 6345 | (buffer-substring-no-properties | ||
| 6346 | 1 (- (point-max) (if decrypt 0 1)))) | ||
| 6347 | ) | ||
| 6348 | |||
| 6349 | ;; validate result -- non-empty | ||
| 6350 | (cond ((not result-text) | ||
| 6351 | (if verifying | ||
| 6352 | nil | ||
| 6353 | ;; transform was fruitless, retry w/new passphrase. | ||
| 6354 | ;;PGG (pgg-remove-passphrase-from-cache target-cache-id t) | ||
| 6355 | (allout-encrypt-string text decrypt allout-buffer | ||
| 6356 | key-type for-key | ||
| 6357 | ;;PGG nil | ||
| 6358 | (if retried (1+ retried) 1) | ||
| 6359 | rejected verifying nil))) | ||
| 6360 | |||
| 6361 | ;; Retry (within limit) if ciphertext contains rejections: | ||
| 6362 | ((and (not decrypt) | ||
| 6363 | ;; Check for disqualification of this ciphertext: | ||
| 6364 | (let ((regexps reject-ciphertext-regexps) | ||
| 6365 | reject-it) | ||
| 6366 | (while (and regexps (not reject-it)) | ||
| 6367 | (setq reject-it (string-match (car regexps) | ||
| 6368 | result-text)) | ||
| 6369 | (pop regexps)) | ||
| 6370 | reject-it)) | ||
| 6371 | (setq rejections-left (1- rejections-left)) | ||
| 6372 | (if (<= rejections-left 0) | ||
| 6373 | (error (concat "Ciphertext rejected too many times" | ||
| 6374 | " (%s), per `%s'") | ||
| 6375 | allout-encryption-ciphertext-rejection-ceiling | ||
| 6376 | 'allout-encryption-ciphertext-rejection-regexps) | ||
| 6377 | (allout-encrypt-string text decrypt allout-buffer | ||
| 6378 | key-type for-key | ||
| 6379 | ;;PGG nil | ||
| 6380 | retried (1+ rejected) | ||
| 6381 | verifying passphrase))) | ||
| 6382 | ;; Barf if encryption yields extraordinary control chars: | ||
| 6383 | ((and (not decrypt) | ||
| 6384 | (string-match "[\C-a\C-k\C-o-\C-z\C-@]" | ||
| 6385 | result-text)) | ||
| 6386 | (error (concat "Encryption produced non-armored text, which" | ||
| 6387 | "conflicts with allout mode -- reconfigure!"))) | ||
| 6388 | |||
| 6389 | ;; valid result and just verifying or non-symmetric: | ||
| 6390 | ((or verifying (not (equal key-type 'symmetric))) | ||
| 6391 | ;;PGG (if (or verifying decrypt) | ||
| 6392 | ;;PGG (pgg-add-passphrase-to-cache target-cache-id | ||
| 6393 | ;;PGG passphrase t)) | ||
| 6394 | result-text) | ||
| 6395 | |||
| 6396 | ;; valid result and regular symmetric -- "register" | ||
| 6397 | ;; passphrase with mnemonic aids/cache. | ||
| 6398 | (t | ||
| 6399 | (set-buffer allout-buffer) | ||
| 6400 | ;;PGG (if passphrase | ||
| 6401 | ;;PGG (pgg-add-passphrase-to-cache target-cache-id | ||
| 6402 | ;;PGG passphrase t)) | ||
| 6403 | (allout-update-passphrase-mnemonic-aids for-key passphrase | ||
| 6404 | allout-buffer) | ||
| 6405 | result-text) | ||
| 6406 | ) | ||
| 6407 | ) | ||
| 6408 | ) | 6296 | ) |
| 6409 | ) | 6297 | ) |
| 6410 | ;;;_ > allout-obtain-passphrase (for-key ;;PGG cache-id | 6298 | ;;;_ . epg passphrase callback handling (epg uses only for GnuPG v1) |
| 6299 | ;;;_ > allout-epg-passphrase-callback-function (context key-id state) | ||
| 6300 | (defun allout-epg-passphrase-callback-function (context key-id state) | ||
| 6301 | "Handle allout passphrase prompting when used with the emacs epg library. | ||
| 6302 | |||
| 6303 | Note that epg's passphrase callback provision only works when | ||
| 6304 | operating with GnuPG v1. Check your GnuPG version using 'gpg | ||
| 6305 | --version' from the command line. | ||
| 6306 | |||
| 6307 | CONTEXT is an epg context object, per 'epg-make-context'. | ||
| 6308 | |||
| 6309 | KEY-ID is apparently either 'SYM, for symmetric passphrase, or | ||
| 6310 | something else for a key pair, per 'epg-passphrase-callback-function'. | ||
| 6311 | |||
| 6312 | STATE is an allout passphrase state construct, per | ||
| 6313 | 'allout-make-passphrase-state'." | ||
| 6314 | (message "allout-passphrase-callback-function: in")(sit-for 1) | ||
| 6315 | (let* ((allout-buffer (allout-passphrase-state-buffer state)) | ||
| 6316 | (provided (allout-passphrase-state-buffer state))) | ||
| 6317 | (if (eq key-id 'SYM) | ||
| 6318 | (if provided | ||
| 6319 | provided | ||
| 6320 | (let* | ||
| 6321 | ((hint-string | ||
| 6322 | (with-current-buffer allout-buffer | ||
| 6323 | (if (and (not (string= allout-passphrase-hint-string | ||
| 6324 | "")) | ||
| 6325 | (or (equal allout-passphrase-hint-handling 'always) | ||
| 6326 | (and (equal allout-passphrase-hint-handling | ||
| 6327 | 'needed) | ||
| 6328 | retried))) | ||
| 6329 | (format " [%s]" allout-passphrase-hint-string) | ||
| 6330 | ""))) | ||
| 6331 | (verifier-string (allout-get-encryption-passphrase-verifier)) | ||
| 6332 | (passphrase (read-passwd | ||
| 6333 | (format "Passphrase for %s symmetric encryption%s: " | ||
| 6334 | (buffer-name allout-buffer) hint-string)))) | ||
| 6335 | (if allout-passphrase-verifier-handling | ||
| 6336 | (if verifier-string | ||
| 6337 | ;; try verifying against existing verifier. | ||
| 6338 | ;; - successful: return the passphrase. | ||
| 6339 | ;; - unsuccessful: offer to change the verifier | ||
| 6340 | ;; - if change accepted, change verifier and continue | ||
| 6341 | ;; - if change refused, raise an encryption error. | ||
| 6342 | (if (condition-case err | ||
| 6343 | (epg-decrypt-string | ||
| 6344 | (allout-context-epg-passphrase-callback | ||
| 6345 | epg-context allout-buffer passphrase) | ||
| 6346 | verifier-string) | ||
| 6347 | (error nil)) | ||
| 6348 | ;;(allout-update-passphrase-mnemonic-aids for-key passphrase | ||
| 6349 | ;; allout-buffer) | ||
| 6350 | |||
| 6351 | ) | ||
| 6352 | (read-passwd | ||
| 6353 | (if (eq key-id 'PIN) | ||
| 6354 | "Passphrase for PIN: " | ||
| 6355 | (let ((entry (assoc key-id epg-user-id-alist))) | ||
| 6356 | (if entry | ||
| 6357 | (format "Passphrase for %s %s: " key-id (cdr entry)) | ||
| 6358 | (format "Passphrase for %s: " key-id))))))) | ||
| 6359 | ;;;_ > allout-context-epg-passphrase-callback (epg-context buffer | ||
| 6360 | ;;; &optional passphrase) | ||
| 6361 | (defun allout-context-epg-passphrase-callback (epg-context buffer | ||
| 6362 | &optional passphrase) | ||
| 6363 | "Return an epg-context which uses allout's passphrase callback with state. | ||
| 6364 | |||
| 6365 | NOTE that epg's passphrase callback provision only works when | ||
| 6366 | operating with GnuPG v1. Check your GnuPG version using 'gpg | ||
| 6367 | --version' from the command line. | ||
| 6368 | |||
| 6369 | A deep copy of the specified EPG-CONTEXT, per 'epg-make-context', | ||
| 6370 | is used as a template. | ||
| 6371 | |||
| 6372 | BUFFER is the allout outline buffer containing the target text. | ||
| 6373 | |||
| 6374 | Optional PASSPHRASE is an already obtained passphrase to be used for | ||
| 6375 | multiple decryptions, eg when verifying symmetric passphrases." | ||
| 6376 | (let ((new-epg-context (copy-tree epg-context))) | ||
| 6377 | (epg-context-set-passphrase-callback | ||
| 6378 | new-epg-context | ||
| 6379 | (cons #'allout-epg-passphrase-callback-function | ||
| 6380 | (allout-make-passphrase-state buffer passphrase))) | ||
| 6381 | new-epg-context)) | ||
| 6382 | ;;;_ > allout-make-passphrase-state (buffer &optional passphrase) | ||
| 6383 | (defun allout-make-passphrase-state (buffer &optional passphrase) | ||
| 6384 | "Return an allout passphrase state construct. | ||
| 6385 | |||
| 6386 | BUFFER is the allout outline buffer. | ||
| 6387 | |||
| 6388 | Optional PASSPHRASE is used when decrypting to convey an already | ||
| 6389 | obtained passphrase for doing multiple decryptions, eg when doing | ||
| 6390 | verification as part of symmetric passphrse decryption." | ||
| 6391 | (cons buffer passphrase)) | ||
| 6392 | ;;;_ > allout-passphrase-state-buffer (state) | ||
| 6393 | (defun allout-passphrase-state-buffer (state) | ||
| 6394 | "Given an allout passphrase STATE construct, return the buffer." | ||
| 6395 | (car state)) | ||
| 6396 | ;;;_ > allout-passphrase-state-passphrase (state) | ||
| 6397 | (defun allout-passphrase-state-passphrase (state) | ||
| 6398 | "Given an allout passphrase STATE construct, return the passphrase or nil." | ||
| 6399 | (cdr state)) | ||
| 6400 | ;;;_ > ;;PGG allout-obtain-passphrase (for-key ;;PGG cache-id | ||
| 6411 | ;;; prompt-id key-type allout-buffer retried | 6401 | ;;; prompt-id key-type allout-buffer retried |
| 6412 | ;;; ;;PGG fetch-pass) | 6402 | ;;; ;;PGG fetch-pass) |
| 6413 | (defun allout-obtain-passphrase (for-key ;;PGG cache-id | 6403 | (defun allout-obtain-passphrase (for-key ;;PGG cache-id |
| @@ -6541,7 +6531,7 @@ RETRIED is the number of this attempt to obtain this passphrase. | |||
| 6541 | (save-match-data (looking-at "\\*"))) | 6531 | (save-match-data (looking-at "\\*"))) |
| 6542 | ) | 6532 | ) |
| 6543 | ) | 6533 | ) |
| 6544 | ;;;_ > allout-encrypted-key-info (text) | 6534 | ;;;_ > ;;PGG allout-encrypted-key-info (text) |
| 6545 | ;; XXX gpg-specific, alas | 6535 | ;; XXX gpg-specific, alas |
| 6546 | (defun allout-encrypted-key-info (text) | 6536 | (defun allout-encrypted-key-info (text) |
| 6547 | "Return a pair of the key type and identity of a recipient's secret key. | 6537 | "Return a pair of the key type and identity of a recipient's secret key. |
| @@ -6558,7 +6548,7 @@ An error is raised if the text is not encrypted." | |||
| 6558 | (with-temp-buffer | 6548 | (with-temp-buffer |
| 6559 | (insert text) | 6549 | (insert text) |
| 6560 | (let* ((parsed-armor (pgg-parse-armor-region (point-min) (point-max))) | 6550 | (let* ((parsed-armor (pgg-parse-armor-region (point-min) (point-max))) |
| 6561 | (type (if (pgg-gpg-symmetric-key-p parsed-armor) | 6551 | (type (if (assq 'symmetric-key-algorithm (car (cdr parsed-armor))) |
| 6562 | 'symmetric | 6552 | 'symmetric |
| 6563 | 'keypair)) | 6553 | 'keypair)) |
| 6564 | secret-keys first-secret-key for-key-owner) | 6554 | secret-keys first-secret-key for-key-owner) |