diff options
| author | Daiki Ueno | 2011-08-04 15:55:53 +0900 |
|---|---|---|
| committer | Daiki Ueno | 2011-08-04 15:55:53 +0900 |
| commit | eeec79cbfa7d7a45b1436942878ef5ad627a5a31 (patch) | |
| tree | 08f494b08df4543ef044bd89a45fe09a7dd15047 | |
| parent | c74e9d8682a27211336db9745f7b4d6399929b37 (diff) | |
| download | emacs-eeec79cbfa7d7a45b1436942878ef5ad627a5a31.tar.gz emacs-eeec79cbfa7d7a45b1436942878ef5ad627a5a31.zip | |
Make sure GPG keys are usable when composing non-MIME messages (bug#8955).
* mml1991.el (mml1991-epg-find-usable-key)
(mml1991-epg-find-usable-secret-key): New function.
(mml1991-epg-sign): Check if signing key is usable.
(mml1991-epg-encrypt): Check if encrypting key is usable (bug#8955).
| -rw-r--r-- | lisp/gnus/ChangeLog | 7 | ||||
| -rw-r--r-- | lisp/gnus/mml1991.el | 94 |
2 files changed, 82 insertions, 19 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 9029ab8e6fd..b361760f511 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | 2011-08-04 Daiki Ueno <ueno@unixuser.org> | ||
| 2 | |||
| 3 | * mml1991.el (mml1991-epg-find-usable-key) | ||
| 4 | (mml1991-epg-find-usable-secret-key): New function. | ||
| 5 | (mml1991-epg-sign): Check if signing key is usable. | ||
| 6 | (mml1991-epg-encrypt): Check if encrypting key is usable (bug#8955). | ||
| 7 | |||
| 1 | 2011-08-03 Andrew Cohen <cohen@andy.bu.edu> | 8 | 2011-08-03 Andrew Cohen <cohen@andy.bu.edu> |
| 2 | 9 | ||
| 3 | * nnir.el (nnir-read-server-parm): Add an argument to restrict to | 10 | * nnir.el (nnir-read-server-parm): Add an argument to restrict to |
diff --git a/lisp/gnus/mml1991.el b/lisp/gnus/mml1991.el index a5d778845c1..ad9f95796fe 100644 --- a/lisp/gnus/mml1991.el +++ b/lisp/gnus/mml1991.el | |||
| @@ -247,6 +247,10 @@ Whether the passphrase is cached at all is controlled by | |||
| 247 | (autoload 'epg-context-set-textmode "epg") | 247 | (autoload 'epg-context-set-textmode "epg") |
| 248 | (autoload 'epg-context-set-signers "epg") | 248 | (autoload 'epg-context-set-signers "epg") |
| 249 | (autoload 'epg-context-set-passphrase-callback "epg") | 249 | (autoload 'epg-context-set-passphrase-callback "epg") |
| 250 | (autoload 'epg-key-sub-key-list "epg") | ||
| 251 | (autoload 'epg-sub-key-capability "epg") | ||
| 252 | (autoload 'epg-sub-key-validity "epg") | ||
| 253 | (autoload 'epg-sub-key-fingerprint "epg") | ||
| 250 | (autoload 'epg-sign-string "epg") | 254 | (autoload 'epg-sign-string "epg") |
| 251 | (autoload 'epg-encrypt-string "epg") | 255 | (autoload 'epg-encrypt-string "epg") |
| 252 | (autoload 'epg-configuration "epg-config") | 256 | (autoload 'epg-configuration "epg-config") |
| @@ -274,17 +278,59 @@ Whether the passphrase is cached at all is controlled by | |||
| 274 | (cons key-id mml1991-epg-secret-key-id-list)) | 278 | (cons key-id mml1991-epg-secret-key-id-list)) |
| 275 | (copy-sequence passphrase))))) | 279 | (copy-sequence passphrase))))) |
| 276 | 280 | ||
| 281 | (defun mml1991-epg-find-usable-key (keys usage) | ||
| 282 | (catch 'found | ||
| 283 | (while keys | ||
| 284 | (let ((pointer (epg-key-sub-key-list (car keys)))) | ||
| 285 | (while pointer | ||
| 286 | (if (and (memq usage (epg-sub-key-capability (car pointer))) | ||
| 287 | (not (memq 'disabled (epg-sub-key-capability (car pointer)))) | ||
| 288 | (not (memq (epg-sub-key-validity (car pointer)) | ||
| 289 | '(revoked expired)))) | ||
| 290 | (throw 'found (car keys))) | ||
| 291 | (setq pointer (cdr pointer)))) | ||
| 292 | (setq keys (cdr keys))))) | ||
| 293 | |||
| 294 | ;; XXX: since gpg --list-secret-keys does not return validity of each | ||
| 295 | ;; key, `mml1991-epg-find-usable-key' defined above is not enough for | ||
| 296 | ;; secret keys. The function `mml1991-epg-find-usable-secret-key' | ||
| 297 | ;; below looks at appropriate public keys to check usability. | ||
| 298 | (defun mml1991-epg-find-usable-secret-key (context name usage) | ||
| 299 | (let ((secret-keys (epg-list-keys context name t)) | ||
| 300 | secret-key) | ||
| 301 | (while (and (not secret-key) secret-keys) | ||
| 302 | (if (mml1991-epg-find-usable-key | ||
| 303 | (epg-list-keys context (epg-sub-key-fingerprint | ||
| 304 | (car (epg-key-sub-key-list | ||
| 305 | (car secret-keys))))) | ||
| 306 | usage) | ||
| 307 | (setq secret-key (car secret-keys) | ||
| 308 | secret-keys nil) | ||
| 309 | (setq secret-keys (cdr secret-keys)))) | ||
| 310 | secret-key)) | ||
| 311 | |||
| 277 | (defun mml1991-epg-sign (cont) | 312 | (defun mml1991-epg-sign (cont) |
| 278 | (let ((context (epg-make-context)) | 313 | (let ((context (epg-make-context)) |
| 279 | headers cte signers signature) | 314 | headers cte signer-key signers signature) |
| 280 | (if (eq mm-sign-option 'guided) | 315 | (if (eq mm-sign-option 'guided) |
| 281 | (setq signers (epa-select-keys context "Select keys for signing. | 316 | (setq signers (epa-select-keys context "Select keys for signing. |
| 282 | If no one is selected, default secret key is used. " | 317 | If no one is selected, default secret key is used. " |
| 283 | mml1991-signers t)) | 318 | mml1991-signers t)) |
| 284 | (if mml1991-signers | 319 | (if mml1991-signers |
| 285 | (setq signers (mapcar (lambda (name) | 320 | (setq signers (delq nil |
| 286 | (car (epg-list-keys context name t))) | 321 | (mapcar |
| 287 | mml1991-signers)))) | 322 | (lambda (name) |
| 323 | (setq signer-key | ||
| 324 | (mml1991-epg-find-usable-secret-key | ||
| 325 | context name 'sign)) | ||
| 326 | (unless (or signer-key | ||
| 327 | (y-or-n-p | ||
| 328 | (format | ||
| 329 | "No secret key for %s; skip it? " | ||
| 330 | name))) | ||
| 331 | (error "No secret key for %s" name)) | ||
| 332 | signer-key) | ||
| 333 | mml1991-signers))))) | ||
| 288 | (epg-context-set-armor context t) | 334 | (epg-context-set-armor context t) |
| 289 | (epg-context-set-textmode context t) | 335 | (epg-context-set-textmode context t) |
| 290 | (epg-context-set-signers context signers) | 336 | (epg-context-set-signers context signers) |
| @@ -344,7 +390,11 @@ If no one is selected, default secret key is used. " | |||
| 344 | (split-string | 390 | (split-string |
| 345 | (message-options-get 'message-recipients) | 391 | (message-options-get 'message-recipients) |
| 346 | "[ \f\t\n\r\v,]+"))) | 392 | "[ \f\t\n\r\v,]+"))) |
| 347 | cipher signers config) | 393 | recipient-key signer-key cipher signers config) |
| 394 | (when mml1991-encrypt-to-self | ||
| 395 | (unless mml1991-signers | ||
| 396 | (error "mml1991-signers is not set")) | ||
| 397 | (setq recipients (nconc recipients mml1991-signers))) | ||
| 348 | ;; We should remove this check if epg-0.0.6 is released. | 398 | ;; We should remove this check if epg-0.0.6 is released. |
| 349 | (if (and (condition-case nil | 399 | (if (and (condition-case nil |
| 350 | (require 'epg-config) | 400 | (require 'epg-config) |
| @@ -363,26 +413,32 @@ If no one is selected, default secret key is used. " | |||
| 363 | If no one is selected, symmetric encryption will be performed. " | 413 | If no one is selected, symmetric encryption will be performed. " |
| 364 | recipients)) | 414 | recipients)) |
| 365 | (setq recipients | 415 | (setq recipients |
| 366 | (delq nil (mapcar (lambda (name) | 416 | (delq nil (mapcar |
| 367 | (car (epg-list-keys context name))) | 417 | (lambda (name) |
| 368 | recipients)))) | 418 | (setq recipient-key (mml1991-epg-find-usable-key |
| 369 | (if mml1991-encrypt-to-self | 419 | (epg-list-keys context name) |
| 370 | (if mml1991-signers | 420 | 'encrypt)) |
| 371 | (setq recipients | 421 | (unless (or recipient-key |
| 372 | (nconc recipients | 422 | (y-or-n-p |
| 373 | (mapcar (lambda (name) | 423 | (format "No public key for %s; skip it? " |
| 374 | (car (epg-list-keys context name))) | 424 | name))) |
| 375 | mml1991-signers))) | 425 | (error "No public key for %s" name)) |
| 376 | (error "mml1991-signers not set"))) | 426 | recipient-key) |
| 427 | recipients))) | ||
| 428 | (unless recipients | ||
| 429 | (error "No recipient specified"))) | ||
| 377 | (when sign | 430 | (when sign |
| 378 | (if (eq mm-sign-option 'guided) | 431 | (if (eq mm-sign-option 'guided) |
| 379 | (setq signers (epa-select-keys context "Select keys for signing. | 432 | (setq signers (epa-select-keys context "Select keys for signing. |
| 380 | If no one is selected, default secret key is used. " | 433 | If no one is selected, default secret key is used. " |
| 381 | mml1991-signers t)) | 434 | mml1991-signers t)) |
| 382 | (if mml1991-signers | 435 | (if mml1991-signers |
| 383 | (setq signers (mapcar (lambda (name) | 436 | (setq signers (delq nil |
| 384 | (car (epg-list-keys context name t))) | 437 | (mapcar |
| 385 | mml1991-signers)))) | 438 | (lambda (name) |
| 439 | (mml1991-epg-find-usable-secret-key | ||
| 440 | context name 'sign)) | ||
| 441 | mml1991-signers))))) | ||
| 386 | (epg-context-set-signers context signers)) | 442 | (epg-context-set-signers context signers)) |
| 387 | (epg-context-set-armor context t) | 443 | (epg-context-set-armor context t) |
| 388 | (epg-context-set-textmode context t) | 444 | (epg-context-set-textmode context t) |