diff options
| author | Daiki Ueno | 2015-08-18 11:55:26 +0900 |
|---|---|---|
| committer | Daiki Ueno | 2015-08-18 11:55:26 +0900 |
| commit | e086e55a664ec27fbca7b3231c4b32cb78a89337 (patch) | |
| tree | 09a3caab25e4a6c8eb9bc9aa93fa00112f799807 | |
| parent | 3a23c477d90ce7401c24de8610be7d1340cd8ee3 (diff) | |
| download | emacs-e086e55a664ec27fbca7b3231c4b32cb78a89337.tar.gz emacs-e086e55a664ec27fbca7b3231c4b32cb78a89337.zip | |
pinentry.el: Support external passphrase cache
* lisp/net/pinentry.el (pinentry-use-secrets): New user option.
(pinentry--allow-external-password-cache): New local variable.
(pinentry--key-info): New local variable.
(secrets-enabled, secrets-search-items, secrets-get-secret):
Declare.
(pinentry--send-passphrase): New function, split from
`pinentry--process-filter'.
(pinentry--process-filter): Use secrets.el to retrieve passphrase
from login keyring.
| -rw-r--r-- | lisp/net/pinentry.el | 151 |
1 files changed, 105 insertions, 46 deletions
diff --git a/lisp/net/pinentry.el b/lisp/net/pinentry.el index 13a15c964ab..aee86473e10 100644 --- a/lisp/net/pinentry.el +++ b/lisp/net/pinentry.el | |||
| @@ -63,6 +63,11 @@ | |||
| 63 | :type 'integer | 63 | :type 'integer |
| 64 | :group 'pinentry) | 64 | :group 'pinentry) |
| 65 | 65 | ||
| 66 | (defcustom pinentry-use-secrets nil | ||
| 67 | "If non-nil, use secrets.el to store passwords in login keyring." | ||
| 68 | :type 'boolean | ||
| 69 | :group 'pinentry) | ||
| 70 | |||
| 66 | (defvar pinentry--server-process nil) | 71 | (defvar pinentry--server-process nil) |
| 67 | (defvar pinentry--connection-process-list nil) | 72 | (defvar pinentry--connection-process-list nil) |
| 68 | 73 | ||
| @@ -70,6 +75,10 @@ | |||
| 70 | (put 'pinentry-read-point 'permanent-local t) | 75 | (put 'pinentry-read-point 'permanent-local t) |
| 71 | (defvar pinentry--read-point nil) | 76 | (defvar pinentry--read-point nil) |
| 72 | (put 'pinentry--read-point 'permanent-local t) | 77 | (put 'pinentry--read-point 'permanent-local t) |
| 78 | (defvar pinentry--allow-external-password-cache nil) | ||
| 79 | (put 'pinentry--allow-external-password-cache 'permanent-local t) | ||
| 80 | (defvar pinentry--key-info nil) | ||
| 81 | (put 'pinentry--key-info 'permanent-local t) | ||
| 73 | 82 | ||
| 74 | (defvar pinentry--prompt-buffer nil) | 83 | (defvar pinentry--prompt-buffer nil) |
| 75 | 84 | ||
| @@ -143,6 +152,10 @@ If local sockets are not supported, this is nil.") | |||
| 143 | (concat prompt (substring short-prompt -2)) | 152 | (concat prompt (substring short-prompt -2)) |
| 144 | query-args))) | 153 | query-args))) |
| 145 | 154 | ||
| 155 | (defvar secrets-enabled) | ||
| 156 | (declare-function secrets-search-items "secrets" (collection &rest attributes)) | ||
| 157 | (declare-function secrets-get-secret "secrets" (collection item)) | ||
| 158 | |||
| 146 | ;;;###autoload | 159 | ;;;###autoload |
| 147 | (defun pinentry-start () | 160 | (defun pinentry-start () |
| 148 | "Start a Pinentry service. | 161 | "Start a Pinentry service. |
| @@ -277,6 +290,23 @@ Assuan protocol." | |||
| 277 | (defun pinentry--send-error (process error) | 290 | (defun pinentry--send-error (process error) |
| 278 | (process-send-string process (format "ERR %d %s\n" (car error) (cdr error)))) | 291 | (process-send-string process (format "ERR %d %s\n" (car error) (cdr error)))) |
| 279 | 292 | ||
| 293 | (defun pinentry--send-passphrase (process passphrase) | ||
| 294 | (let (escaped-passphrase encoded-passphrase) | ||
| 295 | (unwind-protect | ||
| 296 | (condition-case nil | ||
| 297 | (progn | ||
| 298 | (setq escaped-passphrase (pinentry--escape-string passphrase)) | ||
| 299 | (setq encoded-passphrase (encode-coding-string escaped-passphrase | ||
| 300 | 'utf-8)) | ||
| 301 | (pinentry--send-data process encoded-passphrase) | ||
| 302 | (process-send-string process "OK\n")) | ||
| 303 | (error | ||
| 304 | (pinentry--send-error process pinentry--error-cancelled))) | ||
| 305 | (if escaped-passphrase | ||
| 306 | (clear-string escaped-passphrase)) | ||
| 307 | (if encoded-passphrase | ||
| 308 | (clear-string encoded-passphrase))))) | ||
| 309 | |||
| 280 | (defun pinentry--process-filter (process input) | 310 | (defun pinentry--process-filter (process input) |
| 281 | (unless (buffer-live-p (process-buffer process)) | 311 | (unless (buffer-live-p (process-buffer process)) |
| 282 | (let ((buffer (generate-new-buffer " *pinentry*"))) | 312 | (let ((buffer (generate-new-buffer " *pinentry*"))) |
| @@ -286,7 +316,9 @@ Assuan protocol." | |||
| 286 | (set-buffer-multibyte nil)) | 316 | (set-buffer-multibyte nil)) |
| 287 | (make-local-variable 'pinentry--read-point) | 317 | (make-local-variable 'pinentry--read-point) |
| 288 | (setq pinentry--read-point (point-min)) | 318 | (setq pinentry--read-point (point-min)) |
| 289 | (make-local-variable 'pinentry--labels)))) | 319 | (make-local-variable 'pinentry--labels) |
| 320 | (make-local-variable 'pinentry--allow-external-password-cache) | ||
| 321 | (make-local-variable 'pinentry--key-info)))) | ||
| 290 | (with-current-buffer (process-buffer process) | 322 | (with-current-buffer (process-buffer process) |
| 291 | (save-excursion | 323 | (save-excursion |
| 292 | (goto-char (point-max)) | 324 | (goto-char (point-max)) |
| @@ -311,52 +343,79 @@ Assuan protocol." | |||
| 311 | ("NOP" | 343 | ("NOP" |
| 312 | (ignore-errors | 344 | (ignore-errors |
| 313 | (process-send-string process "OK\n"))) | 345 | (process-send-string process "OK\n"))) |
| 346 | ("OPTION" | ||
| 347 | (if (and pinentry-use-secrets | ||
| 348 | (require 'secrets) | ||
| 349 | secrets-enabled | ||
| 350 | (equal string "allow-external-password-cache")) | ||
| 351 | (setq pinentry--allow-external-password-cache t)) | ||
| 352 | (ignore-errors | ||
| 353 | (process-send-string process "OK\n"))) | ||
| 354 | ("SETKEYINFO" | ||
| 355 | (setq pinentry--key-info string) | ||
| 356 | (ignore-errors | ||
| 357 | (process-send-string process "OK\n"))) | ||
| 314 | ("GETPIN" | 358 | ("GETPIN" |
| 315 | (let ((prompt | 359 | (let (passphrase-sent) |
| 316 | (or (cdr (assq 'desc pinentry--labels)) | 360 | (when (and pinentry--allow-external-password-cache |
| 317 | (cdr (assq 'prompt pinentry--labels)) | 361 | pinentry--key-info) |
| 318 | "")) | 362 | (let ((items |
| 319 | (confirm (not (null (assq 'repeat pinentry--labels)))) | 363 | (secrets-search-items "login" |
| 320 | entry) | 364 | :keygrip pinentry--key-info))) |
| 321 | (if (setq entry (assq 'error pinentry--labels)) | 365 | (if items |
| 322 | (setq prompt (concat "Error: " | 366 | (let (passphrase) |
| 323 | (propertize | 367 | (unwind-protect |
| 324 | (copy-sequence (cdr entry)) | 368 | (progn |
| 325 | 'face 'error) | 369 | (setq passphrase (secrets-get-secret |
| 326 | "\n" | 370 | "login" |
| 327 | prompt))) | 371 | (car items))) |
| 328 | (if (setq entry (assq 'title pinentry--labels)) | 372 | (ignore-errors |
| 329 | (setq prompt (format "[%s] %s" | 373 | (process-send-string |
| 330 | (cdr entry) prompt))) | 374 | process |
| 331 | (let (passphrase escaped-passphrase encoded-passphrase) | 375 | "S PASSWORD_FROM_CACHE\n") |
| 332 | (unwind-protect | 376 | (pinentry--send-passphrase |
| 333 | (condition-case nil | 377 | process passphrase) |
| 334 | (progn | 378 | (setq passphrase-sent t))) |
| 335 | (setq passphrase | 379 | (if passphrase |
| 336 | (pinentry--prompt prompt "Password: " | 380 | (clear-string passphrase))))))) |
| 337 | #'read-passwd confirm)) | 381 | (unless passphrase-sent |
| 338 | (setq escaped-passphrase | 382 | (let ((prompt |
| 339 | (pinentry--escape-string | 383 | (or (cdr (assq 'desc pinentry--labels)) |
| 340 | passphrase)) | 384 | (cdr (assq 'prompt pinentry--labels)) |
| 341 | (setq encoded-passphrase (encode-coding-string | 385 | "")) |
| 342 | escaped-passphrase | 386 | (confirm |
| 343 | 'utf-8)) | 387 | (not (null (assq 'repeat pinentry--labels)))) |
| 344 | (ignore-errors | 388 | entry) |
| 345 | (pinentry--send-data | 389 | (if (setq entry (assq 'error pinentry--labels)) |
| 346 | process encoded-passphrase) | 390 | (setq prompt (concat "Error: " |
| 347 | (process-send-string process "OK\n"))) | 391 | (propertize |
| 348 | (error | 392 | (copy-sequence (cdr entry)) |
| 349 | (ignore-errors | 393 | 'face 'error) |
| 350 | (pinentry--send-error | 394 | "\n" |
| 351 | process | 395 | prompt))) |
| 352 | pinentry--error-cancelled)))) | 396 | (if (setq entry (assq 'title pinentry--labels)) |
| 353 | (if passphrase | 397 | (setq prompt (format "[%s] %s" |
| 354 | (clear-string passphrase)) | 398 | (cdr entry) prompt))) |
| 355 | (if escaped-passphrase | 399 | (let (passphrase) |
| 356 | (clear-string escaped-passphrase)) | 400 | (unwind-protect |
| 357 | (if encoded-passphrase | 401 | (condition-case nil |
| 358 | (clear-string encoded-passphrase)))) | 402 | (progn |
| 359 | (setq pinentry--labels nil))) | 403 | (setq passphrase |
| 404 | (pinentry--prompt prompt "Password: " | ||
| 405 | #'read-passwd | ||
| 406 | confirm)) | ||
| 407 | (ignore-errors | ||
| 408 | (pinentry--send-passphrase process | ||
| 409 | passphrase) | ||
| 410 | (process-send-string process "OK\n"))) | ||
| 411 | (error | ||
| 412 | (ignore-errors | ||
| 413 | (pinentry--send-error | ||
| 414 | process | ||
| 415 | pinentry--error-cancelled)))) | ||
| 416 | (if passphrase | ||
| 417 | (clear-string passphrase)))) | ||
| 418 | (setq pinentry--labels nil))))) | ||
| 360 | ("CONFIRM" | 419 | ("CONFIRM" |
| 361 | (let ((prompt | 420 | (let ((prompt |
| 362 | (or (cdr (assq 'desc pinentry--labels)) | 421 | (or (cdr (assq 'desc pinentry--labels)) |