gpgme_op_delete doesn't return failure when loopback mode is enabled
Open, NormalPublic

Description

Consider the following program:

#include <gpgme.h>

int
main (int argc, char *argv[])
{
  gpgme_ctx_t ctx;
  gpgme_error_t err;

  const char *version = gpgme_check_version (NULL);
  printf("gpgme version: %s\n", version);

  err = gpgme_new (&ctx);
  if (err)
    {
      printf ("gpgme_new: %s (%d)\n", gpgme_strerror (err), err);
      return 1;
    }

  const char *fpr = "CD25ED96421EC550CBC581CD6572DDCA38F80155";
  gpgme_key_t key;

  err = gpgme_get_key (ctx, fpr, &key, 0);
  if (err)
    {
      printf ("gpgme_get_key (%s): %s (%d)\n", fpr, gpgme_strerror (err), err);
      return 1;
    }

  gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);

  err = gpgme_op_delete (ctx, key, 1);
  if (err)
    {
      printf ("gpgme_op_delete: %s (%d)\n", gpgme_strerror (err), err);
      return 1;
    }

  gpgme_key_unref (key);

  return 0;
}

This tries to delete a secret key while loopback mode is enabled. Unfortunately, this program returns success, but it does not actually delete the key in question:

/tmp/tmp.QASe7zmW0e$ gpg -K
/tmp/tmp.QASe7zmW0e/pubring.kbx
-------------------------------
sec   rsa2048 2017-09-19 [SC] [expires: 2019-09-19]
      CD25ED96421EC550CBC581CD6572DDCA38F80155
uid           [ultimate] test@example.com
ssb   rsa2048 2017-09-19 [E]

us@grit:/tmp/tmp.QASe7zmW0e$ ../gpgme/gpgme-test 
gpgme version: 1.8.0
us@grit:/tmp/tmp.QASe7zmW0e$ echo $?
0
/tmp/tmp.QASe7zmW0e$ gpg -K
/tmp/tmp.QASe7zmW0e/pubring.kbx
-------------------------------
sec   rsa2048 2017-09-19 [SC] [expires: 2019-09-19]
      CD25ED96421EC550CBC581CD6572DDCA38F80155
uid           [ultimate] test@example.com
ssb   rsa2048 2017-09-19 [E]

/tmp/tmp.QASe7zmW0e$

Disabling loopback mode causes a pinentry prompt to appear and if the user presses ok, then the key is deleted.

Also, running the equivalent (?) from the command line appears to correctly fail:

$ gpg --batch --pinentry-mode=loopback --delete-secret-keys CD25ED96421EC550CBC581CD6572DDCA38F80155
gpg: deleting secret key failed: No pinentry
gpg: deleting secret subkey failed: No pinentry
gpg: CD25ED96421EC550CBC581CD6572DDCA38F80155: delete key failed: No pinentry
/tmp/tmp.QASe7zmW0e$ echo $?
2

Details

Version
gpg and gpgme from Debian 9 (gpg: 2.1.18-6; gpgme: 1.8.0-3)

Related Objects

neal created this task.Sep 19 2017, 2:49 PM
neal added a project: gpgme.
neal added a comment.Sep 19 2017, 10:25 PM

This is more or less what gpgme does/sees when loopback mode is enabled / disabled:

$ gpg --pinentry-mode=loopback --batch --no-sk-comments --lc-messages en_US.utf8 --lc-ctype en_US.utf8 --status-fd 2 --no-tty --charset utf8
--enable-progress-filter --exit-on-status-write-error --delete-secret-and-public-key CD25ED96421EC550CBC581CD6572DDCA38F80155
[GNUPG:] KEY_CONSIDERED CD25ED96421EC550CBC581CD6572DDCA38F80155 0
gpg: deleting secret key failed: No pinentry
gpg: deleting secret subkey failed: No pinentry
gpg: CD25ED96421EC550CBC581CD6572DDCA38F80155: delete key failed: No pinentry
$ echo $?
2
$ gpg  --batch --no-sk-comments --lc-messages en_US.utf8 --lc-ctype en_US.utf8 --status-fd 2 --no-tty --charset utf8 --enable-progress-filter
--exit-on-status-write-error --delete-secret-and-public-key CD25ED96421EC550CBC581CD6572DDCA38F80155
[GNUPG:] KEY_CONSIDERED CD25ED96421EC550CBC581CD6572DDCA38F80155 0
[GNUPG:] PINENTRY_LAUNCHED 31361 gnome3 1.0.0 ? ? ?
[GNUPG:] PINENTRY_LAUNCHED 31371 gnome3 1.0.0 ? ? ?
$ echo $?
0

The status-fd lines neither indicate failure nor success.

Does gpgme actually check the return code of gpg?

werner triaged this task as Normal priority.Oct 4 2017, 6:31 PM
werner added a subscriber: werner.

No. GPGME can't check return codes because it uses a double fork approach.