* Copyright (C) 2001 Thomas Roessler <roessler@guug.de>
* Oliver Ehli <elmy@acm.org>
* Copyright (C) 2002, 2003, 2004 g10 Code GmbH
- *
- * This file is part of mutt-ng, see http://www.muttng.org/.
- * It's licensed under the GNU General Public License,
- * please see the file GPL in the top level source directory.
+ */
+/*
+ * Copyright © 2006 Pierre Habouzit
*/
#include <lib-lib/lib-lib.h>
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
-#ifdef HAVE_LANGINFO_D_T_FMT
-# include <langinfo.h>
-#endif
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
#include <gpgme.h>
#include <lib-mime/mime.h>
static struct crypt_cache *id_defaults = NULL;
static gpgme_key_t signature_key = NULL;
-/* Show a message that a backend will be invoked. */
-void crypt_invoke_message (int type)
-{
- if (type & APPLICATION_PGP) {
- mutt_message _("Invoking PGP...");
- }
- else if (type & APPLICATION_SMIME) {
- mutt_message _("Invoking S/MIME...");
- }
-}
-
/*
* General helper functions.
*/
}
+/* FIXME: stolen from gpgme to avoid "ambiguous identity" errors */
+static gpgme_error_t
+gpgme_get_key2 (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
+ int secret)
+{
+ gpgme_ctx_t listctx;
+ gpgme_error_t err;
+
+ if (!ctx || !r_key || !fpr)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (strlen (fpr) < 8) /* We have at least a key ID. */
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* FIXME: We use our own context because we have to avoid the user's
+ I/O callback handlers. */
+ err = gpgme_new (&listctx);
+ if (err)
+ return err;
+ gpgme_set_protocol (listctx, gpgme_get_protocol (ctx));
+ err = gpgme_op_keylist_start (listctx, fpr, secret);
+ if (!err)
+ err = gpgme_op_keylist_next (listctx, r_key);
+ gpgme_release (listctx);
+ return err;
+}
+
/* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
The keys must be space delimited. */
static gpgme_key_t *create_recipient_set (const char *keylist,
key. */
buf[i - 1] = 0;
- err = gpgme_get_key (context, buf, &key, 0);
+ err = gpgme_get_key2 (context, buf, &key, 0);
if (!err)
key->uids->validity = GPGME_VALIDITY_FULL;
buf[i - 1] = '!';
}
else
- err = gpgme_get_key (context, buf, &key, 0);
+ err = gpgme_get_key2 (context, buf, &key, 0);
if (!err) {
p_realloc(&rset, rset_n + 1);
if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR)
anybad = 1;
- err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */
+ err = gpgme_get_key2 (ctx, fpr, &key, 0); /* secret key? */
if (!err) {
uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]";
if (!signature_key)
/* Do the actual verification step. With IS_SMIME set to true we
assume S/MIME (surprise!) */
-static int verify_one (BODY * sigbdy, STATE * s,
- const char *tempfile, int is_smime)
+int crypt_verify_one(BODY *sigbdy, STATE *s, FILE *fp, int is_smime)
{
int badsig = -1;
int anywarn = 0;
if (is_smime)
gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64);
- err = gpgme_data_new_from_file (&message, tempfile, 1);
+ err = gpgme_data_new_from_stream(&message, fp);
if (err) {
gpgme_data_release (signature);
mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
return badsig ? 1 : anywarn ? 2 : 0;
}
-int crypt_pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
-{
- return verify_one (sigbdy, s, tempfile, 0);
-}
-
-int crypt_smime_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
-{
- return verify_one (sigbdy, s, tempfile, 1);
-}
-
/*
* Implementation of `decrypt_part'.
*/
if (key_check_cap (key, KEY_CAP_CAN_SIGN))
flags |= KEYFLAG_CANSIGN;
-#if 0 /* DISABLED code */
- if (!flags) {
- /* Bug in gpg. Capabilities are not listed for secret
- keys. Try to deduce them from the algorithm. */
-
- switch (key->subkeys[0].pubkey_algo) {
- case GPGME_PK_RSA:
- flags |= KEYFLAG_CANENCRYPT;
- flags |= KEYFLAG_CANSIGN;
- break;
- case GPGME_PK_ELG_E:
- flags |= KEYFLAG_CANENCRYPT;
- break;
- case GPGME_PK_DSA:
- flags |= KEYFLAG_CANSIGN;
- break;
- }
- }
-#endif /* DISABLED code */
-
for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
k = p_new(crypt_key_t, 1);
k->kobj = key;
return (keylist);
}
-char *crypt_pgp_findkeys (address_t * to, address_t * cc, address_t * bcc)
+int crypt_get_keys (HEADER * msg, char **keylist)
{
- return find_keys (to, cc, bcc, APPLICATION_PGP);
-}
+ /* Do a quick check to make sure that we can find all of the encryption
+ * keys if the user has requested this service.
+ */
-char *crypt_smime_findkeys (address_t * to, address_t * cc, address_t * bcc)
-{
- return find_keys (to, cc, bcc, APPLICATION_SMIME);
+ *keylist = NULL;
+
+ if (msg->security & ENCRYPT) {
+ if (msg->security & APPLICATION_PGP) {
+ set_option(OPTPGPCHECKTRUST);
+ *keylist = find_keys(msg->env->to, msg->env->cc, msg->env->bcc,
+ APPLICATION_PGP);
+ unset_option(OPTPGPCHECKTRUST);
+ if (!*keylist)
+ return -1;
+ }
+
+ if (msg->security & APPLICATION_SMIME) {
+ *keylist = find_keys(msg->env->to, msg->env->cc, msg->env->bcc,
+ APPLICATION_SMIME);
+ if (!*keylist)
+ return -1;
+ }
+ }
+
+ return (0);
}
-static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime)
+
+int crypt_send_menu (HEADER * msg, int *redraw, int is_smime)
{
crypt_key_t *p;
char input_signas[STRING];
choice =
mutt_multi_choice (_
("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
- _("esabpfc"));
+ _("esabpc"));
else
choice =
mutt_multi_choice (_
("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
- _("esabmfc"));
+ _("esabmc"));
switch (choice) {
case 1: /* (e)ncrypt */
break;
case 3: /* sign (a)s */
-/* unset_option(OPTCRYPTCHECKTRUST); */
if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
is_smime ? APPLICATION_SMIME :
APPLICATION_PGP, NULL))) {
break;
case 6: /* (c)lear */
- msg->security = 0;
- break;
+ return msg->security = 0;
}
- if (choice == 6 || choice == 7);
- else if (is_smime) {
+ if (is_smime) {
msg->security &= ~APPLICATION_PGP;
msg->security |= APPLICATION_SMIME;
- }
- else {
+ } else {
msg->security &= ~APPLICATION_SMIME;
msg->security |= APPLICATION_PGP;
}
- return (msg->security);
-}
-
-int crypt_pgp_send_menu(HEADER * msg, int *redraw)
-{
- return gpgme_send_menu(msg, redraw, 0);
-}
-
-int crypt_smime_send_menu(HEADER * msg, int *redraw)
-{
- return gpgme_send_menu (msg, redraw, 1);
+ return msg->security;
}
int crypt_smime_verify_sender (HEADER * h)
return ret;
}
-static void invoke_import(const char *fname, int smime)
+void crypt_invoke_import(FILE *stream, int smime)
{
gpgme_ctx_t ctx = create_gpgme_context(smime);
gpgme_data_t data;
gpgme_error_t err;
- err = gpgme_data_new_from_file(&data, fname, 1);
+ err = gpgme_data_new_from_stream(&data, stream);
if (err) {
mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
gpgme_release(ctx);
return;
}
-void crypt_pgp_invoke_import(const char *fname)
-{
- invoke_import(fname, 0);
-}
-
-void crypt_smime_invoke_import(const char *fname)
+static void pgp_extract_keys_from_attachment(FILE * fp, BODY * top)
{
- invoke_import(fname, 1);
-}
-
-static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top)
-{
- STATE s;
- FILE *tempfp;
- char tempfname[_POSIX_PATH_MAX];
-
- tempfp = m_tempfile(tempfname, sizeof(tempfname), NONULL(MCore.tmpdir), NULL);
- if (tempfp == NULL) {
- mutt_perror (_("Can't create temporary file"));
- return;
- }
-
- p_clear(&s, 1);
+ STATE s;
+ FILE *tmpfp = tmpfile();
- s.fpin = fp;
- s.fpout = tempfp;
+ if (tmpfp == NULL) {
+ mutt_perror (_("Can't create temporary file"));
+ return;
+ }
- mutt_body_handler (top, &s);
+ p_clear(&s, 1);
+ s.fpin = fp;
+ s.fpout = tmpfp;
+ mutt_body_handler(top, &s);
- m_fclose(&tempfp);
- crypt_pgp_invoke_import(tempfname);
- mutt_unlink (tempfname);
+ rewind(tmpfp);
+ crypt_invoke_import(tmpfp, 0);
+ m_fclose(&tmpfp);
}
void crypt_pgp_extract_keys_from_attachment_list(FILE * fp, int tag, BODY * top)
unset_option (OPTDONTHANDLEPGPKEYS);
}
+
+/* TODO */
+
+/* fixme: needs documentation. */
+void crypt_pgp_invoke_getkeys (address_t * addr)
+{
+}
+
+/* Generate a PGP public key attachment. */
+BODY *crypt_pgp_make_key_attachment (char *tempf)
+{
+ return NULL;
+}
+
+/* S/MIME */
+
+/* fixme: Needs documentation. */
+void crypt_smime_getkeys (ENVELOPE * env)
+{
+}
+