X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-crypt%2Fcrypt-gpgme.c;h=07bc706d4e9eebfee37f696c7b512606c163767c;hp=1c6990b64dc3b84352762f517a75950bb44513da;hb=74f4cb56b87554a520eb94b02b91a3ea09c8a564;hpb=38dacbf03fe1a0daa9ce426caaef5582b90006b2 diff --git a/lib-crypt/crypt-gpgme.c b/lib-crypt/crypt-gpgme.c index 1c6990b..07bc706 100644 --- a/lib-crypt/crypt-gpgme.c +++ b/lib-crypt/crypt-gpgme.c @@ -6,54 +6,29 @@ * Copyright (C) 2001 Thomas Roessler * Oliver Ehli * 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 -#ifdef CRYPT_BACKEND_GPGME - -#ifdef HAVE_LOCALE_H -# include -#endif -#ifdef HAVE_LANGINFO_D_T_FMT -# include -#endif -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif - #include #include - #include #include #include +#include "crypt.h" + #include "lib.h" #include "alias.h" -#include #include "handler.h" #include "copy.h" #include "pager.h" #include "recvattach.h" #include "sort.h" -#include "crypt-gpgme.h" - -/* - * Helper macros. - */ -#define digitp(p) (*(p) >= '0' && *(p) <= '9') -#define hexdigitp(a) (digitp (a) \ - || (*(a) >= 'A' && *(a) <= 'F') \ - || (*(a) >= 'a' && *(a) <= 'f')) -#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ - *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) -#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) /* Values used for comparing addresses. */ #define CRYPT_KV_VALID 1 @@ -116,7 +91,7 @@ static void print_utf8 (FILE * fp, const char *buf, ssize_t len) char *tstr; tstr = p_dupstr(buf, len); - mutt_convert_string (&tstr, "utf-8", Charset, M_ICONV_HOOK_FROM); + mutt_convert_string (&tstr, "utf-8", MCharset.charset, M_ICONV_HOOK_FROM); fputs (tstr, fp); p_delete(&tstr); } @@ -348,7 +323,7 @@ static gpgme_data_t body_to_data_object (BODY * a, int convert) int err = 0; gpgme_data_t data; - fptmp = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + fptmp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!fptmp) { mutt_perror (_("Can't create temporary file")); return NULL; @@ -454,7 +429,7 @@ static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp) FILE *fp; ssize_t nread = 0; - fp = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + fp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!fp) { mutt_perror (_("Can't create temporary file")); return NULL; @@ -490,6 +465,33 @@ static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp) } +/* 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, @@ -522,13 +524,13 @@ 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); @@ -685,9 +687,7 @@ static void print_time (time_t t, STATE * s) state_attach_puts (p, s); } -/* - * Implementation of `sign_message'. - */ +/* Implementation of `sign_message'. */ /* Sign the MESSAGE in body A either using OpenPGP or S/MIME when USE_SMIME is passed as true. Returns the new body or NULL on @@ -781,12 +781,12 @@ static BODY *sign_message (BODY * a, int use_smime) } -BODY *pgp_gpgme_sign_message (BODY * a) +BODY *crypt_pgp_sign_message (BODY * a) { return sign_message (a, 0); } -BODY *smime_gpgme_sign_message (BODY * a) +BODY *crypt_smime_sign_message (BODY * a) { return sign_message (a, 1); } @@ -797,7 +797,7 @@ BODY *smime_gpgme_sign_message (BODY * a) /* Encrypt the mail body A to all keys given as space separated keyids or fingerprints in KEYLIST and return the encrypted body. */ -BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign) +BODY *crypt_pgp_encrypt_message (BODY * a, char *keylist, int sign) { char *outfile = NULL; BODY *t; @@ -857,7 +857,7 @@ BODY *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign) /* Encrypt the mail body A to all keys given as space separated fingerprints in KEYLIST and return the S/MIME encrypted body. */ -BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist) +BODY *crypt_smime_build_smime_entity (BODY * a, char *keylist) { char *outfile = NULL; BODY *t; @@ -898,9 +898,7 @@ BODY *smime_gpgme_build_smime_entity (BODY * a, char *keylist) } -/* - * Implementation of `verify_one'. - */ +/* Implementation of `verify_one'. */ /* Display the common attributes of the signature summary SUM. Return 1 if there is is a severe warning. @@ -1012,7 +1010,7 @@ static void show_fingerprint (gpgme_key_t key, STATE * state) is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP); bufsize = m_strlen(prefix) + m_strlen(s) * 4 + 2; - buf = xmalloc(bufsize); + buf = p_new(char, bufsize); m_strcpy(buf, bufsize, prefix); p = buf + m_strlen(buf); if (is_pgp && m_strlen(s) == 40) { /* PGP v4 style formatted. */ @@ -1083,7 +1081,7 @@ static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE * s) /* Show information about one signature. This fucntion is called with the context CTX of a sucessful verification operation and the enumerator IDX which should start at 0 and incremete for each - call/signature. + call/signature. Return values are: 0 for normal procession, 1 for a bad signature, 2 for a signature with a warning or -1 for no more signature. */ @@ -1122,7 +1120,7 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE * s) 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) @@ -1297,12 +1295,12 @@ static int verify_one (BODY * sigbdy, STATE * s, return badsig ? 1 : anywarn ? 2 : 0; } -int pgp_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) +int crypt_pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) { return verify_one (sigbdy, s, tempfile, 0); } -int smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) +int crypt_smime_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) { return verify_one (sigbdy, s, tempfile, 1); } @@ -1447,7 +1445,7 @@ restart: /* Decrypt a PGP/MIME message in FPIN and B and return a new body and the stream in CUR and FPOUT. Returns 0 on success. */ -int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) +int crypt_pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) { char tempfile[_POSIX_PATH_MAX]; STATE s; @@ -1467,7 +1465,7 @@ int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) p_clear(&s, 1); s.fpin = fpin; - *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!*fpout) { mutt_perror (_("Can't create temporary file")); return -1; @@ -1485,7 +1483,7 @@ int pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) /* Decrypt a S/MIME message in FPIN and B and return a new body and the stream in CUR and FPOUT. Returns 0 on success. */ -int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, +int crypt_smime_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) { char tempfile[_POSIX_PATH_MAX]; @@ -1512,7 +1510,7 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, p_clear(&s, 1); s.fpin = fpin; fseeko (s.fpin, b->offset, 0); - tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!tmpfp) { mutt_perror (_("Can't create temporary file")); return -1; @@ -1529,7 +1527,7 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, p_clear(&s, 1); s.fpin = tmpfp; s.fpout = 0; - *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!*fpout) { mutt_perror (_("Can't create temporary file")); return -1; @@ -1564,7 +1562,7 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, p_clear(&s, 1); s.fpin = *fpout; fseeko (s.fpin, bb->offset, 0); - tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + tmpfp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!tmpfp) { mutt_perror (_("Can't create temporary file")); return -1; @@ -1582,7 +1580,7 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, p_clear(&s, 1); s.fpin = tmpfp; s.fpout = 0; - *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!*fpout) { mutt_perror (_("Can't create temporary file")); return -1; @@ -1604,7 +1602,7 @@ int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, } -/* +/* * Implementation of `pgp_check_traditional'. */ @@ -1614,6 +1612,7 @@ static int pgp_check_traditional_one_body (FILE * fp, BODY * b, char tempfile[_POSIX_PATH_MAX]; char buf[HUGE_STRING]; FILE *tfp; + int tempfd; short sgn = 0; short enc = 0; @@ -1624,13 +1623,13 @@ static int pgp_check_traditional_one_body (FILE * fp, BODY * b, if (tagged_only && !b->tagged) return 0; - mutt_mktemp (tempfile); - if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0) { + tempfd = m_tempfd(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); + if (mutt_decode_save_attachment (fp, b, tempfd, 0) != 0) { unlink (tempfile); return 0; } - if ((tfp = fopen (tempfile, "r")) == NULL) { + if ((tfp = fopen(tempfile, "r")) == NULL) { unlink (tempfile); return 0; } @@ -1657,14 +1656,14 @@ static int pgp_check_traditional_one_body (FILE * fp, BODY * b, return 1; } -int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only) +int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only) { int rv = 0; int r; for (; b; b = b->next) { if (is_multipart (b)) - rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv); + rv = (crypt_pgp_check_traditional (fp, b->parts, tagged_only) || rv); else if (b->type == TYPETEXT) { if ((r = mutt_is_application_pgp (b))) rv = (rv || r); @@ -1676,18 +1675,16 @@ int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only) } -/* - * Implementation of `application_handler'. - */ +/* Implementation of `application_handler'. */ -/* +/* Copy a clearsigned message, and strip the signature and PGP's dash-escaping. - + XXX - charset handling: We assume that it is safe to do character set decoding first, dash decoding second here, while we do it the other way around in the main handler. - + (Note that we aren't worse than Outlook & Cie in this, and also note that we can successfully handle anything produced by any existing versions of mutt.) */ @@ -1706,7 +1703,7 @@ static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset) unlink (fname); p_delete(&fname); - fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM); + fc = fgetconv_open (fp, charset, MCharset.charset, M_ICONV_HOOK_FROM); for (complete = 1, armor_header = 1; fgetconvs (buf, sizeof (buf), fc) != NULL; @@ -1741,7 +1738,7 @@ static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset) /* Support for classic_application/pgp */ -int pgp_gpgme_application_handler (BODY * m, STATE * s) +int crypt_pgp_application_pgp_handler (BODY * m, STATE * s) { int needpass = -1, pgp_keyblock = 0; int clearsign = 0; @@ -1903,7 +1900,7 @@ int pgp_gpgme_application_handler (BODY * m, STATE * s) /* * Now, copy cleartext to the screen. NOTE - we expect that PGP - * outputs utf-8 cleartext. This may not always be true, but it + * outputs utf-8 cleartext. This may not always be true, but it * seems to be a reasonable guess. */ @@ -1924,7 +1921,7 @@ int pgp_gpgme_application_handler (BODY * m, STATE * s) int c; rewind (pgpout); - fc = fgetconv_open (pgpout, "utf-8", Charset, 0); + fc = fgetconv_open (pgpout, "utf-8", MCharset.charset, 0); while ((c = fgetconv (fc)) != EOF) { state_putc (c, s); if (c == '\n' && s->prefix) @@ -1965,12 +1962,10 @@ int pgp_gpgme_application_handler (BODY * m, STATE * s) return (err); } -/* - * Implementation of `encrypted_handler'. - */ +/* Implementation of `encrypted_handler'. */ /* MIME handler for pgp/mime encrypted messages. */ -int pgp_gpgme_encrypted_handler (BODY * a, STATE * s) +int crypt_pgp_encrypted_handler (BODY * a, STATE * s) { char tempfile[_POSIX_PATH_MAX]; FILE *fpout; @@ -1993,7 +1988,7 @@ int pgp_gpgme_encrypted_handler (BODY * a, STATE * s) /* Move forward to the application/pgp-encrypted body. */ a = a->next; - fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!fpout) { if (s->flags & M_DISPLAY) state_attach_puts (_("[-- Error: could not create temporary file! " @@ -2019,7 +2014,7 @@ int pgp_gpgme_encrypted_handler (BODY * a, STATE * s) s->fpin = savefp; } - /* + /* * if a multipart/signed is the _only_ sub-part of a * multipart/encrypted, cache signature verification * status. @@ -2044,7 +2039,7 @@ int pgp_gpgme_encrypted_handler (BODY * a, STATE * s) } /* Support for application/smime */ -int smime_gpgme_application_handler (BODY * a, STATE * s) +int crypt_smime_application_smime_handler (BODY * a, STATE * s) { char tempfile[_POSIX_PATH_MAX]; FILE *fpout; @@ -2053,7 +2048,7 @@ int smime_gpgme_application_handler (BODY * a, STATE * s) int rc = 0; a->warnsig = 0; - fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!fpout) { if (s->flags & M_DISPLAY) state_attach_puts (_("[-- Error: could not create temporary file! " @@ -2078,7 +2073,7 @@ int smime_gpgme_application_handler (BODY * a, STATE * s) s->fpin = savefp; } - /* + /* * if a multipart/signed is the _only_ sub-part of a * multipart/encrypted, cache signature verification * status. @@ -2110,7 +2105,7 @@ int smime_gpgme_application_handler (BODY * a, STATE * s) /* * Format an entry on the CRYPT key selection menu. - * + * * %n number * %k key id %K key id of the principal key * %u user id @@ -2308,11 +2303,10 @@ crypt_entry_fmt (char *dest, ssize_t destlen, char op, *dest = '\0'; } - if (optional) - m_strformat (dest, destlen, ifstr, mutt_attach_fmt, data, 0); - else if (flags & M_FORMAT_OPTIONAL) - m_strformat (dest, destlen, elstr, mutt_attach_fmt, data, 0); - return (src); + if (flags & M_FORMAT_OPTIONAL) + m_strformat(dest, destlen, 0, optional ? ifstr: elstr, + mutt_attach_fmt, data, 0); + return src; } /* Used by the display fucntion to format a line. */ @@ -2324,8 +2318,7 @@ static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num) entry.key = key_table[num]; entry.num = num + 1; - m_strformat(s, l, NONULL (PgpEntryFormat), crypt_entry_fmt, - (void*)&entry, + m_strformat(s, l, COLS - SW, PgpEntryFormat, crypt_entry_fmt, &entry, option(OPTARROWCURSOR) ? M_FORMAT_ARROWCURSOR : 0); } @@ -2512,16 +2505,16 @@ static const unsigned char *parse_dn_part (struct dn_array_s *array, if (*string == '#') { /* hexstring */ string++; - for (s = string; hexdigitp (s); s++) + for (s = string; hexval(*s) >= 0; s++) s++; n = s - string; if (!n || (n & 1)) return NULL; /* empty or odd number of digits */ n /= 2; - p = xmalloc(n + 1); + p = p_new(unsigned char, n + 1); array->value = (char *) p; for (s1 = string; n; s1 += 2, n--) - *p++ = xtoi_2 (s1); + *p++ = (hexval(*s1) << 8) | hexval(*s1); *p = 0; } else { /* regular v3 quoted string */ @@ -2532,7 +2525,7 @@ static const unsigned char *parse_dn_part (struct dn_array_s *array, || *s == '<' || *s == '>' || *s == '#' || *s == ';' || *s == '\\' || *s == '\"' || *s == ' ') n++; - else if (hexdigitp (s) && hexdigitp (s + 1)) { + else if (hexval(*s) >= 0 && hexval(*s + 1) >= 0) { s++; n++; } @@ -2548,13 +2541,13 @@ static const unsigned char *parse_dn_part (struct dn_array_s *array, n++; } - p = xmalloc(n + 1); + p = p_new(unsigned char, n + 1); array->value = (char *) p; for (s = string; n; s++, n--) { if (*s == '\\') { s++; - if (hexdigitp (s)) { - *p++ = xtoi_2 (s); + if (hexval(*s) >= 0) { + *p++ = (hexval(*s) << 8) | hexval(*s + 1); s++; } else @@ -2926,7 +2919,7 @@ static void verify_key (crypt_key_t * key) gpgme_key_t k = NULL; int maxdepth = 100; - fp = m_tempfile (tempfile, sizeof(tempfile), NONULL(Tempdir), NULL); + fp = m_tempfile (tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL); if (!fp) { mutt_perror (_("Can't create temporary file")); return; @@ -2976,10 +2969,7 @@ leave: mutt_do_pager (cmd, tempfile, 0, NULL); } -/* - * Implementation of `findkeys'. - */ - +/* Implementation of `findkeys'. */ /* Convert string_list_t into a pattern string suitable to be passed to GPGME. We need to convert spaces in an item into a '+' and '%' into @@ -3097,26 +3087,6 @@ static crypt_key_t *get_candidates (string_list_t * hints, unsigned int app, 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; @@ -3477,17 +3447,17 @@ static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities, if (matches) { if (the_valid_key && !multi && !weak && !(invalid && option (OPTPGPSHOWUNUSABLE))) { - /* + /* * There was precisely one strong match on a valid ID, there * were no valid keys with weak matches, and we aren't * interested in seeing invalid keys. - * + * * Proceed without asking the user. */ k = crypt_copy_key (the_valid_key); } else { - /* + /* * Else: Ask the user. */ k = crypt_select_key (matches, a, NULL, app, forced_valid); @@ -3719,41 +3689,17 @@ static char *find_keys (address_t * to, address_t * cc, address_t * bcc, return (keylist); } -char *pgp_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc) +char *crypt_pgp_findkeys (address_t * to, address_t * cc, address_t * bcc) { return find_keys (to, cc, bcc, APPLICATION_PGP); } -char *smime_gpgme_findkeys (address_t * to, address_t * cc, address_t * bcc) +char *crypt_smime_findkeys (address_t * to, address_t * cc, address_t * bcc) { return find_keys (to, cc, bcc, APPLICATION_SMIME); } -/* - * Implementation of `init'. - */ - -/* Initialization. */ -static void init_gpgme (void) -{ - /* Make sure that gpg-agent is running. */ - if (!getenv ("GPG_AGENT_INFO")) { - mutt_error ("\nUsing GPGME backend, although no gpg-agent is running"); - if (mutt_any_key_to_continue (NULL) == -1) - mutt_exit (1); - } -} - -void pgp_gpgme_init (void) -{ - init_gpgme (); -} - -void smime_gpgme_init (void) -{ -} - -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]; @@ -3768,12 +3714,12 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime) 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 */ @@ -3787,7 +3733,6 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime) 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))) { @@ -3811,34 +3756,21 @@ static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime) 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 pgp_gpgme_send_menu (HEADER * msg, int *redraw) -{ - return gpgme_send_menu (msg, redraw, 0); -} - -int smime_gpgme_send_menu (HEADER * msg, int *redraw) -{ - return gpgme_send_menu (msg, redraw, 1); + return msg->security; } -static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((unused))) +int crypt_smime_verify_sender (HEADER * h) { address_t *sender = NULL; unsigned int ret = 1; @@ -3883,9 +3815,86 @@ static int verify_sender (HEADER * h, gpgme_protocol_t protocol __attribute__((u return ret; } -int smime_gpgme_verify_sender (HEADER * h) +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_stream(&data, stream); + if (err) { + mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); + gpgme_release(ctx); + return; + } + + err = gpgme_op_import(ctx, data); + if (err) { + mutt_error(_("error importing gpg data: %s\n"), gpgme_strerror(err)); + gpgme_data_release(data); + gpgme_release(ctx); + return; + } + + gpgme_data_release(data); + gpgme_release(ctx); + return; +} + +static void pgp_extract_keys_from_attachment(FILE * fp, BODY * top) +{ + STATE s; + FILE *tmpfp = tmpfile(); + + if (tmpfp == NULL) { + mutt_perror (_("Can't create temporary file")); + return; + } + + p_clear(&s, 1); + s.fpin = fp; + s.fpout = tmpfp; + mutt_body_handler(top, &s); + + rewind(tmpfp); + crypt_invoke_import(tmpfp, 0); + m_fclose(&tmpfp); +} + +void crypt_pgp_extract_keys_from_attachment_list(FILE * fp, int tag, BODY * top) +{ + mutt_endwin (NULL); + set_option (OPTDONTHANDLEPGPKEYS); + + for (; top; top = top->next) { + if (!tag || top->tagged) + pgp_extract_keys_from_attachment (fp, top); + + if (!tag) + break; + } + + 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) { - return verify_sender (h, GPGME_PROTOCOL_CMS); } -#endif