goto cleanup;
}
- if (mutt_autocrypt_gpgme_create_key (addr, keyid, keydata))
+ if (mutt_autocrypt_gpgme_select_or_create_key (addr, keyid, keydata))
goto cleanup;
/* L10N:
return rv;
}
+int mutt_autocrypt_gpgme_select_key (BUFFER *keyid, BUFFER *keydata)
+{
+ int rv = -1;
+ gpgme_ctx_t ctx = NULL;
+ gpgme_key_t key = NULL;
+
+ set_option (OPTAUTOCRYPTGPGME);
+ if (mutt_gpgme_select_secret_key (keyid))
+ goto cleanup;
+
+ if (create_gpgme_context (&ctx))
+ goto cleanup;
+
+ if (gpgme_get_key (ctx, mutt_b2s (keyid), &key, 0))
+ goto cleanup;
+
+ if (key->revoked || key->expired || key->disabled || key->invalid ||
+ !key->can_encrypt || !key->can_sign)
+ {
+ /* L10N:
+ After selecting a key for an autocrypt account,
+ this is displayed if the key was revoked/expired/disabled/invalid
+ or can't be used for both signing and encryption.
+ %s is the key fingerprint.
+ */
+ mutt_error (_("The key %s is not usable for autocrypt"), mutt_b2s (keyid));
+ mutt_sleep (1);
+ goto cleanup;
+ }
+
+ if (export_keydata (ctx, key, keydata))
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ unset_option (OPTAUTOCRYPTGPGME);
+ gpgme_key_unref (key);
+ gpgme_release (ctx);
+ return rv;
+}
+
+int mutt_autocrypt_gpgme_select_or_create_key (ADDRESS *addr, BUFFER *keyid, BUFFER *keydata)
+{
+ int rv = -1;
+ char *prompt, *letters;
+ int choice;
+
+ /* L10N:
+ During autocrypt account creation, this prompt asks the
+ user whether they want to create a new GPG key for the account,
+ or select an existing account from the keyring.
+ */
+ prompt = _("(c)reate new, or (s)elect existing GPG key? ");
+ /* L10N:
+ The letters corresponding to the
+ "(c)reate new, or (s)elect existing GPG key?" prompt.
+ */
+ letters = _("cs");
+
+ choice = mutt_multi_choice (prompt, letters);
+ switch (choice)
+ {
+ case 2: /* select existing */
+ rv = mutt_autocrypt_gpgme_select_key (keyid, keydata);
+ if (rv == 0)
+ break;
+
+ /* L10N:
+ During autocrypt account creation, if selecting an existing key fails
+ for some reason, we prompt to see if they want to create a key instead.
+ */
+ if (mutt_yesorno (_("Create a new gpg key for this account, instead?"),
+ MUTT_YES) == MUTT_NO)
+ break;
+
+ /* otherwise fall through to create new key */
+
+ case 1: /* create new */
+ rv = mutt_autocrypt_gpgme_create_key (addr, keyid, keydata);
+ }
+
+ return rv;
+}
+
int mutt_autocrypt_gpgme_import_key (const char *keydata, BUFFER *keyid)
{
int rv = -1;
int mutt_autocrypt_schema_update (void);
int mutt_autocrypt_gpgme_init (void);
+int mutt_autocrypt_gpgme_select_or_create_key (ADDRESS *addr, BUFFER *keyid, BUFFER *keydata);
int mutt_autocrypt_gpgme_create_key (ADDRESS *addr, BUFFER *keyid, BUFFER *keydata);
+int mutt_autocrypt_gpgme_select_key (BUFFER *keyid, BUFFER *keydata);
int mutt_autocrypt_gpgme_import_key (const char *keydata, BUFFER *keyid);
int mutt_autocrypt_gpgme_is_valid_key (const char *keyid);
return find_keys (adrlist, APPLICATION_SMIME, oppenc_mode);
}
+/*
+ * This function is used by autocrypt to select a private key for
+ * a new account.
+ *
+ * Unfortunately, the internal crypt-gpgme.c functions use crypt_key_t,
+ * and so aren't exportable.
+ *
+ * This function queries all private keys, provides the crypt_select_keys()
+ * menu, and returns the selected key fingerprint in keyid.
+ */
+int mutt_gpgme_select_secret_key (BUFFER *keyid)
+{
+ int rv = -1, junk;
+ gpgme_ctx_t ctx = NULL;
+ gpgme_error_t err;
+ gpgme_key_t key;
+ gpgme_user_id_t uid;
+ crypt_key_t *results = NULL, *k, **kend;
+ crypt_key_t *choice = NULL;
+ unsigned int flags, idx;
+
+ ctx = create_gpgme_context (0);
+
+ /* list all secret keys */
+ if (gpgme_op_keylist_start (ctx, NULL, 1))
+ goto cleanup;
+
+ kend = &results;
+
+ while (!(err = gpgme_op_keylist_next (ctx, &key)) )
+ {
+ flags = 0;
+
+ if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT))
+ flags |= KEYFLAG_CANENCRYPT;
+ if (key_check_cap (key, KEY_CAP_CAN_SIGN))
+ flags |= KEYFLAG_CANSIGN;
+
+ if (key->revoked)
+ flags |= KEYFLAG_REVOKED;
+ if (key->expired)
+ flags |= KEYFLAG_EXPIRED;
+ if (key->disabled)
+ flags |= KEYFLAG_DISABLED;
+
+ for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next)
+ {
+ k = safe_calloc (1, sizeof *k);
+ k->kobj = key;
+ gpgme_key_ref (k->kobj);
+ k->idx = idx;
+ k->uid = uid->uid;
+ k->flags = flags;
+ if (uid->revoked)
+ k->flags |= KEYFLAG_REVOKED;
+ k->validity = uid->validity;
+ *kend = k;
+ kend = &k->next;
+ }
+ gpgme_key_unref (key);
+ }
+ if (gpg_err_code (err) != GPG_ERR_EOF)
+ mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err));
+ gpgme_op_keylist_end (ctx);
+
+ if (!results)
+ {
+ /* L10N:
+ mutt_gpgme_select_secret_key() tries to list all secret keys to choose
+ from. This error is displayed if no results were found.
+ */
+ mutt_error (_("No secret keys found"));
+ mutt_sleep (1);
+ goto cleanup;
+ }
+
+ choice = crypt_select_key (results, NULL, "*", APPLICATION_PGP, &junk);
+ if (!(choice && choice->kobj && choice->kobj->subkeys &&
+ choice->kobj->subkeys->fpr))
+ goto cleanup;
+ mutt_buffer_strcpy (keyid, choice->kobj->subkeys->fpr);
+
+ rv = 0;
+
+cleanup:
+ crypt_free_key (&choice);
+ crypt_free_key (&results);
+ gpgme_release (ctx);
+ return rv;
+}
+
BODY *pgp_gpgme_make_key_attachment (char *tempf)
{
crypt_key_t *key = NULL;
void mutt_gpgme_set_sender (const char *sender);
+int mutt_gpgme_select_secret_key (BUFFER *keyid);
+
+
#endif