X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=lib-crypt%2Fcrypt-gpgme.c;h=5bd3173c801955ec20a9818b7fad87914d8a20dd;hb=132d06d5920f9a496a8623acfbbabe9739618489;hp=d9f86da485f6623517fb63d1a0bc64d5e3571480;hpb=21f4fef0f77a6caf41c6f8a15279b2b4e50a2f1a;p=apps%2Fmadmutt.git diff --git a/lib-crypt/crypt-gpgme.c b/lib-crypt/crypt-gpgme.c index d9f86da..5bd3173 100644 --- a/lib-crypt/crypt-gpgme.c +++ b/lib-crypt/crypt-gpgme.c @@ -6,24 +6,13 @@ * 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 HAVE_LOCALE_H -# include -#endif -#ifdef HAVE_LANGINFO_D_T_FMT -# include -#endif -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif - #include #include @@ -82,17 +71,6 @@ typedef struct crypt_entry { 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. */ @@ -487,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, @@ -519,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); @@ -1076,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. */ @@ -1115,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) @@ -1192,8 +1197,7 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE * s) /* 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; @@ -1210,7 +1214,7 @@ static int verify_one (BODY * sigbdy, STATE * s, 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)); @@ -1290,16 +1294,6 @@ static int verify_one (BODY * sigbdy, STATE * s, 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'. */ @@ -1597,7 +1591,7 @@ int crypt_smime_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, } -/* +/* * Implementation of `pgp_check_traditional'. */ @@ -1672,14 +1666,14 @@ int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only) /* 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.) */ @@ -1895,7 +1889,7 @@ int crypt_pgp_application_pgp_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. */ @@ -2009,7 +2003,7 @@ int crypt_pgp_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. @@ -2068,7 +2062,7 @@ int crypt_smime_application_smime_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. @@ -2100,7 +2094,7 @@ int crypt_smime_application_smime_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 @@ -3082,26 +3076,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; @@ -3462,17 +3436,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); @@ -3704,17 +3678,37 @@ static char *find_keys (address_t * to, address_t * cc, address_t * bcc, 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]; @@ -3729,12 +3723,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 */ @@ -3748,7 +3742,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))) { @@ -3772,31 +3765,18 @@ 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 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) @@ -3844,13 +3824,13 @@ 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); @@ -3870,38 +3850,24 @@ static void invoke_import(const char *fname, int smime) return; } -void crypt_pgp_invoke_import(const char *fname) -{ - invoke_import(fname, 0); -} - -void crypt_smime_invoke_import(const char *fname) -{ - invoke_import(fname, 1); -} - -static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top) +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; - } + STATE s; + FILE *tmpfp = tmpfile(); - p_clear(&s, 1); - - 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) @@ -3920,3 +3886,24 @@ 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) +{ +} +