Page MenuHome GnuPG

pinentry/gpg/gpgme/Kleo: Cancel semantics: decryption
Open, NormalPublic

Description

Cancel UI should have well-defined semantics.

Let us consider a scenario of decryption (with multiple methods).

Current situation:

  • gpg supports cancelling one method. Canceled -> it tries another method.
  • gpgme considers that single GPG_ERR_CANCELED means cancelling the whole process of decryption.
  • pinentry-tty and pinentry-curses support GPG_ERR_FULLY_CANCELED by Ctrl-C. But other pinentry implementations have no support (only GPG_ERR_CANCELED).

We could have clear definition like:

  • GPG_ERR_CANCELED means cancelling one method
  • GPG_ERR_FULLY_CANCELED means cancelling all (cancelling the whole process of decryption)
  • meaning of empty input depends on the context (for symmetric encryption, meaning "skip", for example)

If this definition is OK, then we will do:

  • Enhance other pinentry implementations to raise GPG_ERR_FULLY_CANCELED (for example, offering another button or new semantics of closing the dialog forcibly).
  • Modify gpgme state-machine
    • not raise an error by a single GPG_ERR_CANCELED, just record it.
    • raise an error by GPG_ERR_FULLY_CANCELED
    • at the EOF, recorded GPG_ERR_CANCELED raise an error
    • observing new pinentry invocation, clears the cancel record
  • Modify gpg
    • When pinentry returns GPG_ERR_FULLY_CANCELED, cancel all methods

Event Timeline

gniibe triaged this task as Normal priority.Wed, Mar 11, 1:56 AM
gniibe created this task.
gniibe updated the task description. (Show Details)
gniibe renamed this task from pinentry/gpg/gpgme/Kleo: Cancel semantics to pinentry/gpg/gpgme/Kleo: Cancel semantics: decryption.Wed, Mar 11, 2:02 AM

If this definition is OK

All reads fine to me (but I do not have a deeper insights).

Thanks for the well structured explanations!

How do you want to decide whether to show two "Cancel" buttons? How would you call those two "Cancel" buttons? For decryption I can imagine that for example "Try Next Key" and "Cancel Decryption" (or even just "Cancel") would make clear what happens.

For other operations it needs to be checked carefully which button texts would be appropriate. Are there actually any other operations than decryption where a soft Cancel would make sense? In most cases I can think of Kleopatra (or the user via the command line) tells gpg explicitly what to do (and, if relevant, which keys to use) so that I don't see a use case for soft Cancel. Decryption is the outlier because there what happens doesn't depend on the user but on the input.

I'd also like to point out that changing the error code from GPG_ERR_CANCELED to GPG_ERR_FULLY_CANCELED could cause regressions in applications.

For a very long time Error::isCanceled() in gpgme++ only checked for GPG_ERR_CANCELED but not for GPG_ERR_FULLY_CANCELED which caused bugs (e.g. T6510) because pinentry-gtk returned GPG_ERR_FULLY_CANCELED if the pinentry window was closed with the window close button (which makes absolutely no sense because almost always pressing the Cancel button, pressing the Esc key and pressing the window close button are treated as identical).

I wouldn't be surprised if other users of gpgme also only check for GPG_ERR_CANCELED because GPG_ERR_FULLY_CANCELED is almost never used.

Also note the comment I added to the fix for Error::isCanceled():

For internal purposes, GnuPG sometimes uses the error code GPG_ERR_FULLY_CANCELED instead of GPG_ERR_CANCELED. From a user perspective both values mean the same thing and should therefore be treated identically.

pinentry-tty and pinentry-curses support GPG_ERR_FULLY_CANCELED by Ctrl-C. But other pinentry implementations have no support (only GPG_ERR_CANCELED).

Not quite true. The GTK pinentry uses the delete event (the window close button in the frame) to issue a FULLY_CANCELED. This is actually done vial a status line and an error code mapping in gpg-agent:

$ pinentry-gtk-2 -g
OK Pleased to meet you, process 8722
getpin 
S BUTTON_INFO close
ERR 83886179 Operation cancelled <Pinentry>

The no-global-grab option is required so that the user may click into the frame.

/* Change error code in case the window close button was clicked
   to cancel the operation.  */
if ((parm->status & PINENTRY_STATUS_CLOSE_BUTTON)
    && gpg_err_code (rc) == GPG_ERR_CANCELED)
  rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);

I stand partially corrected. Apparently, pinentry-efl also sets close_button. For Gpg4win that's irrelevant because we ship pinentry-qt which doesn't have this IMHO contra-intuitive behavior (and pinentry-w32 where I don't know how it behaves).

gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Mar 16, 7:01 AM

I investigated the introduction of STATUS_CANCELED_BY_USER and GPGME_STATUS_CANCELED_BY_USER:
rG31e47dfad0f4: gpg: Add canceled status message.
rM35ca460019ea: Parse STATUS_CANCELED_BY_USER.

It seems that the intention was: a single STATUS_CANCELED_BY_USER deserves full cancellation.

Let us confirm the intention of this change, so that we can go forward.

I can't remember why Ben introduced the new status. OTOH, I wish that the Qt-Pinentry also emits a button_info line for closing the window. Normal users don't notice the difference but if you have a lot of private keys and you get a mail which has only hidden recipients the full_canceled is pretty useful. Also for other tasks like allow-mark-trusted: On Windows with the qt-pinentry I am always cursing about this but on my box I only need to close the pinentry window to get a fully_canceled

I consider again about Ben's change. It could be simply support of the detection of the cancel situation where gpgme should return GPG_ERR_CANCELED (not related to single cancellation vs. whole cancellation).

Here is a patch for gpgme to support cancelling some of methods in decryption:

If my theory about Ben's change is correct, this patch doesn't change the behavior of gpg+gpgme, but support the case when a user cancels one of public keys and then another key successfully decrypts.

gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Mar 23, 3:43 AM