X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=crypt-gpgme.c;h=b9b7613c4421bdccbd02940d33c67a36cce686e5;hp=884319525c672e33dd440d265732007f168f942e;hb=fe23f004535336d4d6103eada14a59173c212edb;hpb=f404a0ca916be07049af51a3022baaaaab94def6 diff --git a/crypt-gpgme.c b/crypt-gpgme.c index 8843195..b9b7613 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -1,23 +1,15 @@ -/* crypt-gpgme.c - GPGME based crypto operations +/* + * Copyright notice from original mutt: + * crypt-gpgme.c - GPGME based crypto operations * Copyright (C) 1996,1997 Michael R. Elkins * Copyright (C) 1998,1999,2000 Thomas Roessler * Copyright (C) 2001 Thomas Roessler * Oliver Ehli * Copyright (C) 2002, 2003, 2004 g10 Code GmbH * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * 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. */ #if HAVE_CONFIG_H @@ -35,6 +27,11 @@ #include "pager.h" #include "sort.h" +#include "lib/mem.h" +#include "lib/intl.h" +#include "lib/str.h" +#include "lib/debug.h" + #include #include #include @@ -82,32 +79,28 @@ * Type definitions. */ -struct crypt_cache -{ +struct crypt_cache { char *what; char *dflt; struct crypt_cache *next; }; -struct dn_array_s -{ +struct dn_array_s { char *key; char *value; }; /* We work based on user IDs, getting from a user ID to the key is check and does not need any memory (gpgme uses reference counting). */ -typedef struct crypt_keyinfo -{ +typedef struct crypt_keyinfo { struct crypt_keyinfo *next; gpgme_key_t kobj; - int idx; /* and the user ID at this index */ - const char *uid; /* and for convenience point to this user ID */ - unsigned int flags; /* global and per uid flags (for convenience)*/ + int idx; /* and the user ID at this index */ + const char *uid; /* and for convenience point to this user ID */ + unsigned int flags; /* global and per uid flags (for convenience) */ } crypt_key_t; -typedef struct crypt_entry -{ +typedef struct crypt_entry { size_t num; crypt_key_t *key; } crypt_entry_t; @@ -120,24 +113,22 @@ static gpgme_key_t signature_key = NULL; * General helper functions. */ -/* return true when S pints to a didgit or letter. */ -static int -digit_or_letter (const unsigned char *s) +/* return true when S points to a didgit or letter. */ +static int digit_or_letter (const unsigned char *s) { - return ( (*s >= '0' && *s < '9') - || (*s >= 'A' && *s <= 'Z') - || (*s >= 'a' && *s <= 'z')); + return ((*s >= '0' && *s <= '9') + || (*s >= 'A' && *s <= 'Z') + || (*s >= 'a' && *s <= 'z')); } /* Print the utf-8 encoded string BUF of length LEN bytes to stream FP. Convert the character set. */ -static void -print_utf8 (FILE *fp, const char *buf, size_t len) +static void print_utf8 (FILE * fp, const char *buf, size_t len) { char *tstr; - tstr = safe_malloc (len+1); + tstr = safe_malloc (len + 1); memcpy (tstr, buf, len); tstr[len] = 0; mutt_convert_string (&tstr, "utf-8", Charset, M_ICONV_HOOK_FROM); @@ -152,23 +143,22 @@ print_utf8 (FILE *fp, const char *buf, size_t len) /* Return the keyID for the key K. Note that this string is valid as long as K is valid */ -static const char *crypt_keyid (crypt_key_t *k) +static const char *crypt_keyid (crypt_key_t * k) { const char *s = "????????"; - if (k->kobj && k->kobj->subkeys) - { - s = k->kobj->subkeys->keyid; - if ((! option (OPTPGPLONGIDS)) && (strlen (s) == 16)) - /* Return only the short keyID. */ - s += 8; - } + if (k->kobj && k->kobj->subkeys) { + s = k->kobj->subkeys->keyid; + if ((!option (OPTPGPLONGIDS)) && (mutt_strlen (s) == 16)) + /* Return only the short keyID. */ + s += 8; + } return s; } /* Return the hexstring fingerprint from the key K. */ -static const char *crypt_fpr (crypt_key_t *k) +static const char *crypt_fpr (crypt_key_t * k) { const char *s = ""; @@ -213,12 +203,12 @@ static char crypt_flags (int flags) return 'd'; else if (flags & KEYFLAG_CRITICAL) return 'c'; - else + else return ' '; } /* Return a copy of KEY. */ -static crypt_key_t *crypt_copy_key (crypt_key_t *key) +static crypt_key_t *crypt_copy_key (crypt_key_t * key) { crypt_key_t *k; @@ -234,18 +224,18 @@ static crypt_key_t *crypt_copy_key (crypt_key_t *key) /* Release all the keys at the address of KEYLIST and set the address to NULL. */ -static void crypt_free_key (crypt_key_t **keylist) +static void crypt_free_key (crypt_key_t ** keylist) { - while (*keylist) - { - crypt_key_t *k = (*keylist)->next; - FREE (&k); - *keylist = k; - } + while (*keylist) { + crypt_key_t *k = (*keylist)->next; + + FREE (&k); + *keylist = k; + } } /* Return trute when key K is valid. */ -static int crypt_key_is_valid (crypt_key_t *k) +static int crypt_key_is_valid (crypt_key_t * k) { if (k->flags & KEYFLAG_CANTUSE) return 0; @@ -253,7 +243,7 @@ static int crypt_key_is_valid (crypt_key_t *k) } /* Return true whe validity of KEY is sufficient. */ -static int crypt_id_is_strong (crypt_key_t *key) +static int crypt_id_is_strong (crypt_key_t * key) { gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN; gpgme_user_id_t uid = NULL; @@ -264,56 +254,54 @@ static int crypt_id_is_strong (crypt_key_t *key) return 1; for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid; - i++, uid = uid->next) - ; + i++, uid = uid->next); if (uid) val = uid->validity; - switch (val) - { - case GPGME_VALIDITY_UNKNOWN: - case GPGME_VALIDITY_UNDEFINED: - case GPGME_VALIDITY_NEVER: - case GPGME_VALIDITY_MARGINAL: - is_strong = 0; - break; + switch (val) { + case GPGME_VALIDITY_UNKNOWN: + case GPGME_VALIDITY_UNDEFINED: + case GPGME_VALIDITY_NEVER: + case GPGME_VALIDITY_MARGINAL: + is_strong = 0; + break; - case GPGME_VALIDITY_FULL: - case GPGME_VALIDITY_ULTIMATE: - is_strong = 1; - break; - } + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: + is_strong = 1; + break; + } return is_strong; } /* Return true when the KEY is valid, i.e. not marked as unusable. */ -static int crypt_id_is_valid (crypt_key_t *key) +static int crypt_id_is_valid (crypt_key_t * key) { - return ! (key->flags & KEYFLAG_CANTUSE); + return !(key->flags & KEYFLAG_CANTUSE); } /* Return a bit vector describing how well the addresses ADDR and U_ADDR match and whether KEY is valid. */ -static int crypt_id_matches_addr (ADDRESS *addr, ADDRESS *u_addr, - crypt_key_t *key) +static int crypt_id_matches_addr (ADDRESS * addr, ADDRESS * u_addr, + crypt_key_t * key) { int rv = 0; - + if (crypt_id_is_valid (key)) rv |= CRYPT_KV_VALID; if (crypt_id_is_strong (key)) rv |= CRYPT_KV_STRONGID; - + if (addr->mailbox && u_addr->mailbox - && mutt_strcasecmp (addr->mailbox, u_addr->mailbox) == 0) + && safe_strcasecmp (addr->mailbox, u_addr->mailbox) == 0) rv |= CRYPT_KV_ADDR; - + if (addr->personal && u_addr->personal - && mutt_strcasecmp (addr->personal, u_addr->personal) == 0) + && safe_strcasecmp (addr->personal, u_addr->personal) == 0) rv |= CRYPT_KV_STRING; - + return rv; } @@ -330,24 +318,20 @@ static gpgme_ctx_t create_gpgme_context (int for_smime) gpgme_ctx_t ctx; err = gpgme_new (&ctx); - if (err) - { - mutt_error ("error creating gpgme context: %s\n", gpgme_strerror (err)); + if (err) { + mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err)); + sleep (2); + mutt_exit (1); + } + + if (for_smime) { + err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + if (err) { + mutt_error (_("error enabling CMS protocol: %s\n"), gpgme_strerror (err)); sleep (2); mutt_exit (1); } - - if (for_smime) - { - err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); - if (err) - { - mutt_error ("error enabling CMS protocol: %s\n", - gpgme_strerror (err)); - sleep (2); - mutt_exit (1); - } - } + } return ctx; } @@ -360,77 +344,69 @@ static gpgme_data_t create_gpgme_data (void) gpgme_data_t data; err = gpgme_data_new (&data); - if (err) - { - mutt_error ("error creating gpgme data object: %s\n", - gpgme_strerror (err)); - sleep (2); - mutt_exit (1); - } + if (err) { + mutt_error (_("error creating gpgme data object: %s\n"), + gpgme_strerror (err)); + sleep (2); + mutt_exit (1); + } return data; } /* Create a new GPGME Data object from the mail body A. With CONVERT passed as true, the lines are converted to CR,LF if required. Return NULL on error or the gpgme_data_t object on success. */ -static gpgme_data_t body_to_data_object (BODY *a, int convert) +static gpgme_data_t body_to_data_object (BODY * a, int convert) { char tempfile[_POSIX_PATH_MAX]; FILE *fptmp; int err = 0; gpgme_data_t data; - + mutt_mktemp (tempfile); fptmp = safe_fopen (tempfile, "w+"); - if (!fptmp) - { - mutt_perror (tempfile); - return NULL; - } + if (!fptmp) { + mutt_perror (tempfile); + return NULL; + } mutt_write_mime_header (a, fptmp); fputc ('\n', fptmp); mutt_write_mime_body (a, fptmp); - if (convert) - { - int c, hadcr = 0; - unsigned char buf[1]; - - data = create_gpgme_data (); - rewind (fptmp); - while ((c = fgetc (fptmp)) != EOF) - { - if (c == '\r') - hadcr = 1; - else - { - if (c == '\n' && !hadcr) - { - buf[0] = '\r'; - gpgme_data_write (data, buf, 1); - } - - hadcr = 0; - } - /* FIXME: This is quite suboptimal */ - buf[0] = c; + if (convert) { + int c, hadcr = 0; + unsigned char buf[1]; + + data = create_gpgme_data (); + rewind (fptmp); + while ((c = fgetc (fptmp)) != EOF) { + if (c == '\r') + hadcr = 1; + else { + if (c == '\n' && !hadcr) { + buf[0] = '\r'; gpgme_data_write (data, buf, 1); } - fclose(fptmp); - gpgme_data_seek (data, 0, SEEK_SET); - } - else - { - fclose(fptmp); - err = gpgme_data_new_from_file (&data, tempfile, 1); + + hadcr = 0; + } + /* FIXME: This is quite suboptimal */ + buf[0] = c; + gpgme_data_write (data, buf, 1); } + fclose (fptmp); + gpgme_data_seek (data, 0, SEEK_SET); + } + else { + fclose (fptmp); + err = gpgme_data_new_from_file (&data, tempfile, 1); + } unlink (tempfile); - if (err) - { - mutt_error ("error allocating data object: %s\n", gpgme_strerror (err)); - return NULL; - } + if (err) { + mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); + return NULL; + } return data; } @@ -438,23 +414,22 @@ static gpgme_data_t body_to_data_object (BODY *a, int convert) /* Create a GPGME data object from the stream FP but limit the object to LENGTH bytes starting at OFFSET bytes from the beginning of the file. */ -static gpgme_data_t file_to_data_object (FILE *fp, long offset, long length) +static gpgme_data_t file_to_data_object (FILE * fp, long offset, long length) { int err = 0; gpgme_data_t data; - + err = gpgme_data_new_from_filepart (&data, NULL, fp, offset, length); - if (err) - { - mutt_error ("error allocating data object: %s\n", gpgme_strerror (err)); - return NULL; - } + if (err) { + mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); + return NULL; + } return data; } /* Write a GPGME data object to the stream FP. */ -static int data_object_to_stream (gpgme_data_t data, FILE *fp) +static int data_object_to_stream (gpgme_data_t data, FILE * fp) { int err; char buf[4096], *p; @@ -462,40 +437,35 @@ static int data_object_to_stream (gpgme_data_t data, FILE *fp) err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno (errno) : 0); - if (err) - { - mutt_error ("error rewinding data object: %s\n", gpgme_strerror (err)); - return -1; - } - - while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) - { - /* fixme: we are not really converting CRLF to LF but just - skipping CR. Doing it correctly needs a more complex logic */ - for (p=buf; nread; p++, nread--) - { - if (*p != '\r') - putc (*p, fp); - } + if (err) { + mutt_error (_("error rewinding data object: %s\n"), gpgme_strerror (err)); + return -1; + } - if (ferror (fp)) - { - mutt_perror ("[tempfile]"); - return -1; - } + while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) { + /* fixme: we are not really converting CRLF to LF but just + skipping CR. Doing it correctly needs a more complex logic */ + for (p = buf; nread; p++, nread--) { + if (*p != '\r') + putc (*p, fp); } - if (nread == -1) - { - mutt_error ("error reading data object: %s\n", strerror (errno)); + + if (ferror (fp)) { + mutt_perror ("[tempfile]"); return -1; } + } + if (nread == -1) { + mutt_error (_("error reading data object: %s\n"), strerror (errno)); + return -1; + } return 0; } /* Copy a data object to a newly created temporay file and return that filename. Caller must free. With RET_FP not NULL, don't close the stream but return it there. */ -static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp) +static char *data_object_to_tempfile (gpgme_data_t data, FILE ** ret_fp) { int err; char tempfile[_POSIX_PATH_MAX]; @@ -504,40 +474,35 @@ static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp) mutt_mktemp (tempfile); fp = safe_fopen (tempfile, "w+"); - if (!fp) - { - mutt_perror (tempfile); - return NULL; - } + if (!fp) { + mutt_perror (tempfile); + return NULL; + } err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno (errno) : 0); - if (!err) - { - char buf[4096]; - - while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) - { - if (fwrite (buf, nread, 1, fp) != 1) - { - mutt_perror (tempfile); - fclose (fp); - unlink (tempfile); - return NULL; - } - } + if (!err) { + char buf[4096]; + + while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) { + if (fwrite (buf, nread, 1, fp) != 1) { + mutt_perror (tempfile); + fclose (fp); + unlink (tempfile); + return NULL; + } } + } if (ret_fp) rewind (fp); else fclose (fp); - if (nread == -1) - { - mutt_error ("error reading data object: %s\n", gpgme_strerror (err)); - unlink (tempfile); - fclose (fp); - return NULL; - } + if (nread == -1) { + mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err)); + unlink (tempfile); + fclose (fp); + return NULL; + } if (ret_fp) *ret_fp = fp; return safe_strdup (tempfile); @@ -559,54 +524,49 @@ static gpgme_key_t *create_recipient_set (const char *keylist, gpgme_ctx_t context = NULL; err = gpgme_new (&context); - if (! err) + if (!err) err = gpgme_set_protocol (context, protocol); - if (! err) - { - s = keylist; - do { - while (*s == ' ') - s++; - for (i=0; *s && *s != ' ' && i < sizeof(buf)-1;) - buf[i++] = *s++; - buf[i] = 0; - if (*buf) - { - if (i>1 && buf[i-1] == '!') - { - /* The user selected to override the valididy of that - key. */ - buf[i-1] = 0; - - err = gpgme_get_key (context, buf, &key, 0); - if (! err) - key->uids->validity = GPGME_VALIDITY_FULL; - buf[i-1] = '!'; - } - else - err = gpgme_get_key (context, buf, &key, 0); - - if (! err) - { - safe_realloc (&rset, sizeof (*rset) * (rset_n + 1)); - rset[rset_n++] = key; - } - else - { - mutt_error ("error adding recipient `%s': %s\n", - buf, gpgme_strerror (err)); - FREE (&rset); - return NULL; - } - } - } while (*s); - } + if (!err) { + s = keylist; + do { + while (*s == ' ') + s++; + for (i = 0; *s && *s != ' ' && i < sizeof (buf) - 1;) + buf[i++] = *s++; + buf[i] = 0; + if (*buf) { + if (i > 1 && buf[i - 1] == '!') { + /* The user selected to override the valididy of that + key. */ + buf[i - 1] = 0; + + err = gpgme_get_key (context, buf, &key, 0); + if (!err) + key->uids->validity = GPGME_VALIDITY_FULL; + buf[i - 1] = '!'; + } + else + err = gpgme_get_key (context, buf, &key, 0); + + if (!err) { + safe_realloc (&rset, sizeof (*rset) * (rset_n + 1)); + rset[rset_n++] = key; + } + else { + mutt_error (_("error adding recipient `%s': %s\n"), + buf, gpgme_strerror (err)); + FREE (&rset); + return NULL; + } + } + } while (*s); + } /* NULL terminate. */ safe_realloc (&rset, sizeof (*rset) * (rset_n + 1)); rset[rset_n++] = NULL; - + if (context) gpgme_release (context); @@ -617,7 +577,7 @@ static gpgme_key_t *create_recipient_set (const char *keylist, /* Make sure that the correct signer is set. Returns 0 on success. */ static int set_signer (gpgme_ctx_t ctx, int for_smime) { - char *signid = for_smime ? SmimeDefaultKey: PgpSignAs; + char *signid = for_smime ? SmimeDefaultKey : PgpSignAs; gpgme_error_t err; gpgme_ctx_t listctx; gpgme_key_t key, key2; @@ -629,35 +589,31 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime) err = gpgme_op_keylist_start (listctx, signid, 1); if (!err) err = gpgme_op_keylist_next (listctx, &key); - if (err) - { - gpgme_release (listctx); - mutt_error (_("secret key `%s' not found: %s\n"), - signid, gpgme_strerror (err)); - return -1; - } + if (err) { + gpgme_release (listctx); + mutt_error (_("secret key `%s' not found: %s\n"), + signid, gpgme_strerror (err)); + return -1; + } err = gpgme_op_keylist_next (listctx, &key2); - if (!err) - { - gpgme_key_release (key); - gpgme_key_release (key2); - gpgme_release (listctx); - mutt_error (_("ambiguous specfication of secret key `%s'\n"), - signid); - return -1; - } + if (!err) { + gpgme_key_release (key); + gpgme_key_release (key2); + gpgme_release (listctx); + mutt_error (_("ambiguous specification of secret key `%s'\n"), signid); + return -1; + } gpgme_op_keylist_end (listctx); gpgme_release (listctx); gpgme_signers_clear (ctx); err = gpgme_signers_add (ctx, key); gpgme_key_release (key); - if (err) - { - mutt_error (_("error setting secret key `%s': %s\n"), - signid, gpgme_strerror (err)); - return -1; - } + if (err) { + mutt_error (_("error setting secret key `%s': %s\n"), + signid, gpgme_strerror (err)); + return -1; + } return 0; } @@ -667,7 +623,7 @@ static int set_signer (gpgme_ctx_t ctx, int for_smime) enciphered text. With USE_SMIME set to true, the smime backend is used. With COMBINED_SIGNED a PGP message is signed and encrypted. Returns NULL in case of error */ -static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset, +static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t * rset, int use_smime, int combined_signed) { int err; @@ -676,33 +632,30 @@ static char *encrypt_gpgme_object (gpgme_data_t plaintext, gpgme_key_t *rset, char *outfile; ctx = create_gpgme_context (use_smime); - if (!use_smime) - gpgme_set_armor (ctx, 1); + if (!use_smime) + gpgme_set_armor (ctx, 1); ciphertext = create_gpgme_data (); - if (combined_signed) - { - if (set_signer (ctx, use_smime)) - { - gpgme_data_release (ciphertext); - gpgme_release (ctx); - return NULL; - } - err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, - plaintext, ciphertext); + if (combined_signed) { + if (set_signer (ctx, use_smime)) { + gpgme_data_release (ciphertext); + gpgme_release (ctx); + return NULL; } + err = gpgme_op_encrypt_sign (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, + plaintext, ciphertext); + } else err = gpgme_op_encrypt (ctx, rset, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, ciphertext); mutt_need_hard_redraw (); - if (err) - { - mutt_error ("error encrypting data: %s\n", gpgme_strerror (err)); - gpgme_data_release (ciphertext); - gpgme_release (ctx); - return NULL; - } + if (err) { + mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err)); + gpgme_data_release (ciphertext); + gpgme_release (ctx); + return NULL; + } gpgme_release (ctx); @@ -727,20 +680,18 @@ static int get_micalg (gpgme_ctx_t ctx, char *buf, size_t buflen) *buf = 0; result = gpgme_op_sign_result (ctx); - if (result) - { - algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo); - if (algorithm_name) - { - strncpy (buf, algorithm_name, buflen - 1); - buf[buflen - 1] = 0; - } + if (result) { + algorithm_name = gpgme_hash_algo_name (result->signatures->hash_algo); + if (algorithm_name) { + strncpy (buf, algorithm_name, buflen - 1); + buf[buflen - 1] = 0; } + } - return *buf? 0:-1; + return *buf ? 0 : -1; } -static void print_time(time_t t, STATE *s) +static void print_time (time_t t, STATE * s) { char p[STRING]; @@ -761,7 +712,7 @@ static void print_time(time_t t, STATE *s) /* 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 error. */ -static BODY *sign_message (BODY *a, int use_smime) +static BODY *sign_message (BODY * a, int use_smime) { BODY *t; char *sigfile; @@ -770,42 +721,39 @@ static BODY *sign_message (BODY *a, int use_smime) gpgme_ctx_t ctx; gpgme_data_t message, signature; - convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */ + convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */ message = body_to_data_object (a, 1); if (!message) - return NULL; + return NULL; signature = create_gpgme_data (); ctx = create_gpgme_context (use_smime); if (!use_smime) gpgme_set_armor (ctx, 1); - if (set_signer (ctx, use_smime)) - { - gpgme_data_release (signature); - gpgme_release (ctx); - return NULL; - } + if (set_signer (ctx, use_smime)) { + gpgme_data_release (signature); + gpgme_release (ctx); + return NULL; + } - err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH ); + err = gpgme_op_sign (ctx, message, signature, GPGME_SIG_MODE_DETACH); mutt_need_hard_redraw (); gpgme_data_release (message); - if (err) - { - gpgme_data_release (signature); - gpgme_release (ctx); - mutt_error ("error signing data: %s\n", gpgme_strerror (err)); - return NULL; - } + if (err) { + gpgme_data_release (signature); + gpgme_release (ctx); + mutt_error (_("error signing data: %s\n"), gpgme_strerror (err)); + return NULL; + } sigfile = data_object_to_tempfile (signature, NULL); gpgme_data_release (signature); - if (!sigfile) - { - gpgme_release (ctx); - return NULL; - } + if (!sigfile) { + gpgme_release (ctx); + return NULL; + } t = mutt_new_body (); t->type = TYPEMULTIPART; @@ -816,9 +764,8 @@ static BODY *sign_message (BODY *a, int use_smime) mutt_generate_boundary (&t->parameter); mutt_set_parameter ("protocol", - use_smime? "application/pkcs7-signature" - : "application/pgp-signature", - &t->parameter); + use_smime ? "application/pkcs7-signature" + : "application/pgp-signature", &t->parameter); /* Get the micalg from gpgme. Old gpgme versions don't support this for S/MIME so we assume sha-1 in this case. */ if (!get_micalg (ctx, buf, sizeof buf)) @@ -833,35 +780,33 @@ static BODY *sign_message (BODY *a, int use_smime) t->parts->next = mutt_new_body (); t = t->parts->next; t->type = TYPEAPPLICATION; - if (use_smime) - { - t->subtype = safe_strdup ("pkcs7-signature"); - mutt_set_parameter ("name", "smime.p7s", &t->parameter); - t->encoding = ENCBASE64; - t->use_disp = 1; - t->disposition = DISPATTACH; - t->d_filename = safe_strdup ("smime.p7s"); - } - else - { - t->subtype = safe_strdup ("pgp-signature"); - t->use_disp = 0; - t->disposition = DISPINLINE; - t->encoding = ENC7BIT; - } + if (use_smime) { + t->subtype = safe_strdup ("pkcs7-signature"); + mutt_set_parameter ("name", "smime.p7s", &t->parameter); + t->encoding = ENCBASE64; + t->use_disp = 1; + t->disposition = DISPATTACH; + t->d_filename = safe_strdup ("smime.p7s"); + } + else { + t->subtype = safe_strdup ("pgp-signature"); + t->use_disp = 0; + t->disposition = DISPINLINE; + t->encoding = ENC7BIT; + } t->filename = sigfile; - t->unlink = 1; /* ok to remove this file after sending. */ + t->unlink = 1; /* ok to remove this file after sending. */ return a; } -BODY *pgp_gpgme_sign_message (BODY *a) +BODY *pgp_gpgme_sign_message (BODY * a) { return sign_message (a, 0); } -BODY *smime_gpgme_sign_message (BODY *a) +BODY *smime_gpgme_sign_message (BODY * a) { return sign_message (a, 1); } @@ -872,31 +817,30 @@ 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 *pgp_gpgme_encrypt_message (BODY * a, char *keylist, int sign) { char *outfile = NULL; BODY *t; gpgme_key_t *rset = NULL; gpgme_data_t plaintext; - + rset = create_recipient_set (keylist, GPGME_PROTOCOL_OpenPGP); if (!rset) return NULL; - + if (sign) convert_to_7bit (a); plaintext = body_to_data_object (a, 0); - if (!plaintext) - { - FREE (&rset); - return NULL; - } - + if (!plaintext) { + FREE (&rset); + return NULL; + } + outfile = encrypt_gpgme_object (plaintext, rset, 0, sign); gpgme_data_release (plaintext); FREE (&rset); if (!outfile) - return NULL; + return NULL; t = mutt_new_body (); t->type = TYPEMULTIPART; @@ -905,9 +849,9 @@ BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign) t->use_disp = 0; t->disposition = DISPINLINE; - mutt_generate_boundary(&t->parameter); - mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter); - + mutt_generate_boundary (&t->parameter); + mutt_set_parameter ("protocol", "application/pgp-encrypted", &t->parameter); + t->parts = mutt_new_body (); t->parts->type = TYPEAPPLICATION; t->parts->subtype = safe_strdup ("pgp-encrypted"); @@ -920,7 +864,7 @@ BODY *pgp_gpgme_encrypt_message (BODY *a, char *keylist, int sign) t->parts->next->filename = outfile; t->parts->next->use_disp = 1; t->parts->next->disposition = DISPINLINE; - t->parts->next->unlink = 1; /* delete after sending the message */ + t->parts->next->unlink = 1; /* delete after sending the message */ t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime can save */ @@ -933,7 +877,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 *smime_gpgme_build_smime_entity (BODY * a, char *keylist) { char *outfile = NULL; BODY *t; @@ -945,32 +889,31 @@ BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist) return NULL; plaintext = body_to_data_object (a, 0); - if (!plaintext) - { - FREE (&rset); - return NULL; - } + if (!plaintext) { + FREE (&rset); + return NULL; + } outfile = encrypt_gpgme_object (plaintext, rset, 1, 0); gpgme_data_release (plaintext); FREE (&rset); - if (!outfile) - return NULL; + if (!outfile) + return NULL; t = mutt_new_body (); t->type = TYPEAPPLICATION; t->subtype = safe_strdup ("pkcs7-mime"); mutt_set_parameter ("name", "smime.p7m", &t->parameter); mutt_set_parameter ("smime-type", "enveloped-data", &t->parameter); - t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */ + t->encoding = ENCBASE64; /* The output of OpenSSL SHOULD be binary */ t->use_disp = 1; t->disposition = DISPATTACH; t->d_filename = safe_strdup ("smime.p7m"); t->filename = outfile; - t->unlink = 1; /*delete after sending the message */ - t->parts=0; - t->next=0; - + t->unlink = 1; /*delete after sending the message */ + t->parts = 0; + t->next = 0; + return t; } @@ -983,108 +926,97 @@ BODY *smime_gpgme_build_smime_entity (BODY *a, char *keylist) Return 1 if there is is a severe warning. */ static int show_sig_summary (unsigned long sum, - gpgme_ctx_t ctx, gpgme_key_t key, int idx, - STATE *s) + gpgme_ctx_t ctx, gpgme_key_t key, int idx, + STATE * s) { int severe = 0; - if ((sum & GPGME_SIGSUM_KEY_REVOKED)) - { - state_attach_puts (_("Warning: One of the keys has been revoked\n"),s); - severe = 1; - } + if ((sum & GPGME_SIGSUM_KEY_REVOKED)) { + state_attach_puts (_("Warning: One of the keys has been revoked\n"), s); + severe = 1; + } - if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) - { - time_t at = key->subkeys->expires ? key->subkeys->expires : 0; - if (at) - { - state_attach_puts (_("Warning: The key used to create the " - "signature expired at: "), s); - print_time (at , s); - state_attach_puts ("\n", s); - } - else - state_attach_puts (_("Warning: At least one certification key " - "has expired\n"), s); - } + if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) { + time_t at = key->subkeys->expires ? key->subkeys->expires : 0; - if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) - { - gpgme_verify_result_t result; - gpgme_signature_t sig; - unsigned int i; - - result = gpgme_op_verify_result (ctx); - - for (sig = result->signatures, i = 0; sig && (i < idx); - sig = sig->next, i++) - ; - - state_attach_puts (_("Warning: The signature expired at: "), s); - print_time (sig ? sig->exp_timestamp : 0, s); + if (at) { + state_attach_puts (_("Warning: The key used to create the " + "signature expired at: "), s); + print_time (at, s); state_attach_puts ("\n", s); } + else + state_attach_puts (_("Warning: At least one certification key " + "has expired\n"), s); + } + + if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) { + gpgme_verify_result_t result; + gpgme_signature_t sig; + unsigned int i; + + result = gpgme_op_verify_result (ctx); + + for (sig = result->signatures, i = 0; sig && (i < idx); + sig = sig->next, i++); + + state_attach_puts (_("Warning: The signature expired at: "), s); + print_time (sig ? sig->exp_timestamp : 0, s); + state_attach_puts ("\n", s); + } if ((sum & GPGME_SIGSUM_KEY_MISSING)) state_attach_puts (_("Can't verify due to a missing " "key or certificate\n"), s); - if ((sum & GPGME_SIGSUM_CRL_MISSING)) - { - state_attach_puts (_("The CRL is not available\n"), s); - severe = 1; - } + if ((sum & GPGME_SIGSUM_CRL_MISSING)) { + state_attach_puts (_("The CRL is not available\n"), s); + severe = 1; + } - if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) - { - state_attach_puts (_("Available CRL is too old\n"), s); - severe = 1; - } + if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) { + state_attach_puts (_("Available CRL is too old\n"), s); + severe = 1; + } if ((sum & GPGME_SIGSUM_BAD_POLICY)) state_attach_puts (_("A policy requirement was not met\n"), s); - if ((sum & GPGME_SIGSUM_SYS_ERROR)) - { - const char *t0 = NULL, *t1 = NULL; - gpgme_verify_result_t result; - gpgme_signature_t sig; - unsigned int i; - - state_attach_puts (_("A system error occured"), s ); - - /* Try to figure out some more detailed system error information. */ - result = gpgme_op_verify_result (ctx); - for (sig = result->signatures, i = 0; sig && (i < idx); - sig = sig->next, i++) - ; - if (sig) - { - t0 = ""; - t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; - } - - if (t0 || t1) - { - state_attach_puts (": ", s); - if (t0) - state_attach_puts (t0, s); - if (t1 && !(t0 && !strcmp (t0, t1))) - { - if (t0) - state_attach_puts (",", s); - state_attach_puts (t1, s); - } - } - state_attach_puts ("\n", s); + if ((sum & GPGME_SIGSUM_SYS_ERROR)) { + const char *t0 = NULL, *t1 = NULL; + gpgme_verify_result_t result; + gpgme_signature_t sig; + unsigned int i; + + state_attach_puts (_("A system error occurred"), s); + + /* Try to figure out some more detailed system error information. */ + result = gpgme_op_verify_result (ctx); + for (sig = result->signatures, i = 0; sig && (i < idx); + sig = sig->next, i++); + if (sig) { + t0 = ""; + t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; + } + + if (t0 || t1) { + state_attach_puts (": ", s); + if (t0) + state_attach_puts (t0, s); + if (t1 && !(t0 && !mutt_strcmp (t0, t1))) { + if (t0) + state_attach_puts (",", s); + state_attach_puts (t1, s); + } } + state_attach_puts ("\n", s); + } return severe; } -static void show_fingerprint (gpgme_key_t key, STATE *state) +static void show_fingerprint (gpgme_key_t key, STATE * state) { const char *s; int i, is_pgp; @@ -1098,33 +1030,29 @@ static void show_fingerprint (gpgme_key_t key, STATE *state) return; is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP); - buf = safe_malloc ( strlen (prefix) + strlen(s) * 4 + 2 ); - strcpy (buf, prefix); /* __STRCPY_CHECKED__ */ - p = buf + strlen (buf); - if (is_pgp && strlen (s) == 40) - { /* PGP v4 style formatted. */ - for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) - { - *p++ = s[0]; - *p++ = s[1]; - *p++ = s[2]; - *p++ = s[3]; - *p++ = ' '; - if (i == 4) - *p++ = ' '; - } + buf = safe_malloc (mutt_strlen (prefix) + mutt_strlen (s) * 4 + 2); + strcpy (buf, prefix); /* __STRCPY_CHECKED__ */ + p = buf + mutt_strlen (buf); + if (is_pgp && mutt_strlen (s) == 40) { /* PGP v4 style formatted. */ + for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) { + *p++ = s[0]; + *p++ = s[1]; + *p++ = s[2]; + *p++ = s[3]; + *p++ = ' '; + if (i == 4) + *p++ = ' '; } - else - { - for (i=0; *s && s[1] && s[2]; s += 2, i++) - { - *p++ = s[0]; - *p++ = s[1]; - *p++ = is_pgp? ' ':':'; - if (is_pgp && i == 7) - *p++ = ' '; - } + } + else { + for (i = 0; *s && s[1] && s[2]; s += 2, i++) { + *p++ = s[0]; + *p++ = s[1]; + *p++ = is_pgp ? ' ' : ':'; + if (is_pgp && i == 7) + *p++ = ' '; } + } /* just in case print remaining odd digits */ for (; *s; s++) @@ -1136,7 +1064,7 @@ static void show_fingerprint (gpgme_key_t key, STATE *state) } /* Show the valididy of a key used for one signature. */ -static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE *s) +static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE * s) { gpgme_verify_result_t result = NULL; gpgme_signature_t sig = NULL; @@ -1146,28 +1074,26 @@ static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE *s) if (result) for (sig = result->signatures; sig && (idx > 0); sig = sig->next, idx--); - switch (sig ? sig->validity : 0) - { - case GPGME_VALIDITY_UNKNOWN: - txt = _("WARNING: We have NO indication whether " - "the key belongs to the person named " - "as shown above\n"); - break; - case GPGME_VALIDITY_UNDEFINED: - break; - case GPGME_VALIDITY_NEVER: - txt = _("WARNING: The key does NOT BELONG to " - "the person named as shown above\n"); - break; - case GPGME_VALIDITY_MARGINAL: - txt = _("WARNING: It is NOT certain that the key " - "belongs to the person named as shown above\n"); - break; - case GPGME_VALIDITY_FULL: - case GPGME_VALIDITY_ULTIMATE: - txt = NULL; - break; - } + switch (sig ? sig->validity : 0) { + case GPGME_VALIDITY_UNKNOWN: + txt = _("WARNING: We have NO indication whether " + "the key belongs to the person named " "as shown above\n"); + break; + case GPGME_VALIDITY_UNDEFINED: + break; + case GPGME_VALIDITY_NEVER: + txt = _("WARNING: The key does NOT BELONG to " + "the person named as shown above\n"); + break; + case GPGME_VALIDITY_MARGINAL: + txt = _("WARNING: It is NOT certain that the key " + "belongs to the person named as shown above\n"); + break; + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: + txt = NULL; + break; + } if (txt) state_attach_puts (txt, s); } @@ -1179,7 +1105,7 @@ static void show_one_sig_validity (gpgme_ctx_t ctx, int idx, STATE *s) 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. */ -static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s) +static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE * s) { time_t created; const char *fpr, *uid; @@ -1192,117 +1118,106 @@ static int show_one_sig_status (gpgme_ctx_t ctx, int idx, STATE *s) gpgme_error_t err = GPG_ERR_NO_ERROR; result = gpgme_op_verify_result (ctx); - if (result) - { - /* FIXME: this code should use a static variable and remember - the current position in the list of signatures, IMHO. - -moritz. */ - - for (i = 0, sig = result->signatures; sig && (i < idx); - i++, sig = sig->next) - ; - if (! sig) - return -1; /* Signature not found. */ - - if (signature_key) - { - gpgme_key_release (signature_key); - signature_key = NULL; - } - - created = sig->timestamp; - fpr = sig->fpr; - sum = sig->summary; - - if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR) - anybad = 1; - - err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */ - if (! err) - { - uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]"; - if (! signature_key) - signature_key = key; - } - else - { - key = NULL; /* Old gpgme versions did not set KEY to NULL on - error. Do it here to avoid a double free. */ - uid = "[?]"; - } - - if (!s || !s->fpout || !(s->flags & M_DISPLAY)) - ; /* No state information so no way to print anything. */ - else if (err) - { - state_attach_puts (_("Error getting key information: "), s); - state_attach_puts ( gpg_strerror (err), s ); - state_attach_puts ("\n", s); - anybad = 1; - } - else if ((sum & GPGME_SIGSUM_GREEN)) - { - state_attach_puts (_("Good signature from: "), s); - state_attach_puts (uid, s); - state_attach_puts ("\n", s); - for (i = 1, uids = key->uids; uids; i++, uids = uids->next) - { - if (i == 1) - /* Skip primary UID. */ - continue; - if (uids->revoked) - continue; - state_attach_puts (_(" aka: "), s); - state_attach_puts (uids->uid, s); - state_attach_puts ("\n", s); - } - state_attach_puts (_(" created: "), s); - print_time (created, s); - state_attach_puts ("\n", s); - if (show_sig_summary (sum, ctx, key, idx, s)) - anywarn = 1; - show_one_sig_validity (ctx, idx, s); - } - else if ((sum & GPGME_SIGSUM_RED)) - { - state_attach_puts (_("*BAD* signature claimed to be from: "), s); - state_attach_puts (uid, s); - state_attach_puts ("\n", s); - show_sig_summary (sum, ctx, key, idx, s); - } - else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) - { /* We can't decide (yellow) but this is a PGP key with a good - signature, so we display what a PGP user expects: The name, - fingerprint and the key validity (which is neither fully or - ultimate). */ - state_attach_puts (_("Good signature from: "), s); - state_attach_puts (uid, s); - state_attach_puts ("\n", s); - state_attach_puts (_(" created: "), s); - print_time (created, s); - state_attach_puts ("\n", s); - show_one_sig_validity (ctx, idx, s); - show_fingerprint (key,s); - if (show_sig_summary (sum, ctx, key, idx, s)) - anywarn = 1; - } - else /* can't decide (yellow) */ - { - state_attach_puts (_("Error checking signature"), s); - state_attach_puts ("\n", s); - show_sig_summary (sum, ctx, key, idx, s); - } - - if (key != signature_key) - gpgme_key_release (key); - } + if (result) { + /* FIXME: this code should use a static variable and remember + the current position in the list of signatures, IMHO. + -moritz. */ + + for (i = 0, sig = result->signatures; sig && (i < idx); + i++, sig = sig->next); + if (!sig) + return -1; /* Signature not found. */ + + if (signature_key) { + gpgme_key_release (signature_key); + signature_key = NULL; + } + + created = sig->timestamp; + fpr = sig->fpr; + sum = sig->summary; + + if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR) + anybad = 1; + + err = gpgme_get_key (ctx, fpr, &key, 0); /* secret key? */ + if (!err) { + uid = (key->uids && key->uids->uid) ? key->uids->uid : "[?]"; + if (!signature_key) + signature_key = key; + } + else { + key = NULL; /* Old gpgme versions did not set KEY to NULL on + error. Do it here to avoid a double free. */ + uid = "[?]"; + } + + if (!s || !s->fpout || !(s->flags & M_DISPLAY)); /* No state information so no way to print anything. */ + else if (err) { + state_attach_puts (_("Error getting key information: "), s); + state_attach_puts (gpg_strerror (err), s); + state_attach_puts ("\n", s); + anybad = 1; + } + else if ((sum & GPGME_SIGSUM_GREEN)) { + state_attach_puts (_("Good signature from: "), s); + state_attach_puts (uid, s); + state_attach_puts ("\n", s); + for (i = 1, uids = key->uids; uids; i++, uids = uids->next) { + if (i == 1) + /* Skip primary UID. */ + continue; + if (uids->revoked) + continue; + state_attach_puts (_(" aka: "), s); + state_attach_puts (uids->uid, s); + state_attach_puts ("\n", s); + } + state_attach_puts (_(" created: "), s); + print_time (created, s); + state_attach_puts ("\n", s); + if (show_sig_summary (sum, ctx, key, idx, s)) + anywarn = 1; + show_one_sig_validity (ctx, idx, s); + } + else if ((sum & GPGME_SIGSUM_RED)) { + state_attach_puts (_("*BAD* signature claimed to be from: "), s); + state_attach_puts (uid, s); + state_attach_puts ("\n", s); + show_sig_summary (sum, ctx, key, idx, s); + } + else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) { /* We can't decide (yellow) but this is a PGP key with a good + signature, so we display what a PGP user expects: The name, + fingerprint and the key validity (which is neither fully or + ultimate). */ + state_attach_puts (_("Good signature from: "), s); + state_attach_puts (uid, s); + state_attach_puts ("\n", s); + state_attach_puts (_(" created: "), s); + print_time (created, s); + state_attach_puts ("\n", s); + show_one_sig_validity (ctx, idx, s); + show_fingerprint (key, s); + if (show_sig_summary (sum, ctx, key, idx, s)) + anywarn = 1; + } + else { /* can't decide (yellow) */ + + state_attach_puts (_("Error checking signature"), s); + state_attach_puts ("\n", s); + show_sig_summary (sum, ctx, key, idx, s); + } + + if (key != signature_key) + gpgme_key_release (key); + } return anybad ? 1 : anywarn ? 2 : 0; } /* Do the actual verification step. With IS_SMIME set to true we assume S/MIME (surprise!) */ -static int verify_one (BODY *sigbdy, STATE *s, +static int verify_one (BODY * sigbdy, STATE * s, const char *tempfile, int is_smime) { int badsig = -1; @@ -1321,12 +1236,11 @@ static int verify_one (BODY *sigbdy, STATE *s, gpgme_data_set_encoding (signature, GPGME_DATA_ENCODING_BASE64); err = gpgme_data_new_from_file (&message, tempfile, 1); - if (err) - { - gpgme_data_release (signature); - mutt_error ("error allocating data object: %s\n", gpgme_strerror (err)); - return -1; - } + if (err) { + gpgme_data_release (signature); + mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); + return -1; + } ctx = create_gpgme_context (is_smime); /* Note: We don't need a current time output because GPGME avoids @@ -1336,90 +1250,79 @@ static int verify_one (BODY *sigbdy, STATE *s, err = gpgme_op_verify (ctx, signature, message, NULL); mutt_need_hard_redraw (); - if (err) - { - char buf[200]; - - snprintf (buf, sizeof(buf)-1, - _("Error: verification failed: %s\n"), - gpgme_strerror (err)); - state_attach_puts (buf, s); - } - else - { /* Verification succeeded, see what the result is. */ - int res, idx; - int anybad = 0; - - if (signature_key) - { - gpgme_key_release (signature_key); - signature_key = NULL; - } - - for(idx=0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) - { - if (res == 1) - anybad = 1; - else if (res == 2) - anywarn = 2; - } - if (!anybad) - badsig = 0; + if (err) { + char buf[200]; + + snprintf (buf, sizeof (buf) - 1, + _("Error: verification failed: %s\n"), gpgme_strerror (err)); + state_attach_puts (buf, s); + } + else { /* Verification succeeded, see what the result is. */ + int res, idx; + int anybad = 0; + + if (signature_key) { + gpgme_key_release (signature_key); + signature_key = NULL; } - if (!badsig) - { - gpgme_verify_result_t result; - gpgme_sig_notation_t notation; - gpgme_signature_t signature; + for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) { + if (res == 1) + anybad = 1; + else if (res == 2) + anywarn = 2; + } + if (!anybad) + badsig = 0; + } - result = gpgme_op_verify_result (ctx); - if (result) - { - for (signature = result->signatures; signature; - signature = signature->next) - { - if (signature->notations) - { - state_attach_puts ("*** Begin Notation (signature by: ", s); - state_attach_puts (signature->fpr, s); - state_attach_puts (") ***\n", s); - for (notation = signature->notations; notation; - notation = notation->next) - { - if (notation->name) - { - state_attach_puts (notation->name, s); - state_attach_puts ("=", s); - } - if (notation->value) - { - state_attach_puts (notation->value, s); - if (!(*notation->value - && (notation->value[strlen (notation->value)-1]=='\n'))) - state_attach_puts ("\n", s); - } - } - state_attach_puts ("*** End Notation ***\n", s); - } - } + if (!badsig) { + gpgme_verify_result_t result; + gpgme_sig_notation_t notation; + gpgme_signature_t signature; + + result = gpgme_op_verify_result (ctx); + if (result) { + for (signature = result->signatures; signature; + signature = signature->next) { + if (signature->notations) { + state_attach_puts ("*** Begin Notation (signature by: ", s); + state_attach_puts (signature->fpr, s); + state_attach_puts (") ***\n", s); + for (notation = signature->notations; notation; + notation = notation->next) { + if (notation->name) { + state_attach_puts (notation->name, s); + state_attach_puts ("=", s); + } + if (notation->value) { + state_attach_puts (notation->value, s); + if (!(*notation->value + && (notation->value[mutt_strlen (notation->value) - 1] == + '\n'))) + state_attach_puts ("\n", s); + } + } + state_attach_puts ("*** End Notation ***\n", s); + } } } + } gpgme_release (ctx); - + state_attach_puts (_("[-- End signature information --]\n\n"), s); - dprint (1, (debugfile, "verify_one: returning %d.\n", badsig)); - - return badsig? 1: anywarn? 2 : 0; + debug_print (1, ("returning %d.\n", badsig)); + + return badsig ? 1 : anywarn ? 2 : 0; } -int pgp_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile) +int pgp_gpgme_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 smime_gpgme_verify_one (BODY * sigbdy, STATE * s, const char *tempfile) { return verify_one (sigbdy, s, tempfile, 1); } @@ -1434,7 +1337,7 @@ int smime_gpgme_verify_one (BODY *sigbdy, STATE *s, const char *tempfile) a flag in R_IS_SIGNED to indicate whether this is a combined encrypted and signed message, for S/MIME it returns true when it is not a encrypted but a signed message. */ -static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime, +static BODY *decrypt_part (BODY * a, STATE * s, FILE * fpout, int is_smime, int *r_is_signed) { struct stat info; @@ -1451,7 +1354,7 @@ static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime, ctx = create_gpgme_context (is_smime); - restart: +restart: /* Make a data object from the body, create context etc. */ ciphertext = file_to_data_object (s->fpin, a->offset, a->length); if (!ciphertext) @@ -1459,144 +1362,133 @@ static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime, plaintext = create_gpgme_data (); /* Do the decryption or the verification in case of the S/MIME hack. */ - if ((! is_smime) || maybe_signed) + if ((!is_smime) || maybe_signed) { + if (!is_smime) + err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext); + else if (maybe_signed) + err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext); + { - if (! is_smime) - err = gpgme_op_decrypt_verify (ctx, ciphertext, plaintext); - else if (maybe_signed) - err = gpgme_op_verify (ctx, ciphertext, NULL, plaintext); + /* Check wether signatures have been verified. */ + gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx); - { - /* Check wether signatures have been verified. */ - gpgme_verify_result_t verify_result = gpgme_op_verify_result (ctx); - if (verify_result->signatures) - sig_stat = 1; - } + if (verify_result->signatures) + sig_stat = 1; } + } else err = gpgme_op_decrypt (ctx, ciphertext, plaintext); gpgme_data_release (ciphertext); - if (err) - { - if (is_smime && !maybe_signed - && gpg_err_code (err) == GPG_ERR_NO_DATA) - { - /* Check whether this might be a signed message despite what - the mime header told us. Retry then. gpgsm returns the - error information "unsupported Algorithm '?'" but gpgme - will not store this unknown algorithm, thus we test that - it has not been set. */ - gpgme_decrypt_result_t result; - - result = gpgme_op_decrypt_result (ctx); - if (!result->unsupported_algorithm) - { - maybe_signed = 1; - gpgme_data_release (plaintext); - goto restart; - } - } - mutt_need_hard_redraw (); - if ((s->flags & M_DISPLAY)) - { - char buf[200]; - - snprintf (buf, sizeof(buf)-1, - _("[-- Error: decryption failed: %s --]\n\n"), - gpgme_strerror (err)); - state_attach_puts (buf, s); - } - gpgme_data_release (plaintext); - gpgme_release (ctx); - return NULL; + if (err) { + if (is_smime && !maybe_signed && gpg_err_code (err) == GPG_ERR_NO_DATA) { + /* Check whether this might be a signed message despite what + the mime header told us. Retry then. gpgsm returns the + error information "unsupported Algorithm '?'" but gpgme + will not store this unknown algorithm, thus we test that + it has not been set. */ + gpgme_decrypt_result_t result; + + result = gpgme_op_decrypt_result (ctx); + if (!result->unsupported_algorithm) { + maybe_signed = 1; + gpgme_data_release (plaintext); + goto restart; + } + } + mutt_need_hard_redraw (); + if ((s->flags & M_DISPLAY)) { + char buf[200]; + + snprintf (buf, sizeof (buf) - 1, + _("[-- Error: decryption failed: %s --]\n\n"), + gpgme_strerror (err)); + state_attach_puts (buf, s); + } + gpgme_data_release (plaintext); + gpgme_release (ctx); + return NULL; } mutt_need_hard_redraw (); /* Read the output from GPGME, and make sure to change CRLF to LF, otherwise read_mime_header has a hard time parsing the message. */ - if (data_object_to_stream (plaintext, fpout)) - { - gpgme_data_release (plaintext); - gpgme_release (ctx); - return NULL; - } + if (data_object_to_stream (plaintext, fpout)) { + gpgme_data_release (plaintext); + gpgme_release (ctx); + return NULL; + } gpgme_data_release (plaintext); a->is_signed_data = 0; - if (sig_stat) - { - int res, idx; - int anybad = 0; - - if (maybe_signed) - a->is_signed_data = 1; - if(r_is_signed) - *r_is_signed = -1; /* A signature exists. */ - - if ((s->flags & M_DISPLAY)) - state_attach_puts (_("[-- Begin signature " - "information --]\n"), s); - for(idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) - { - if (res == 1) - anybad = 1; - else if (res == 2) - anywarn = 1; - } - if (!anybad && idx && r_is_signed && *r_is_signed) - *r_is_signed = anywarn? 2:1; /* Good signature. */ - - if ((s->flags & M_DISPLAY)) - state_attach_puts (_("[-- End signature " - "information --]\n\n"), s); - } - gpgme_release (ctx); ctx = NULL; + if (sig_stat) { + int res, idx; + int anybad = 0; + + if (maybe_signed) + a->is_signed_data = 1; + if (r_is_signed) + *r_is_signed = -1; /* A signature exists. */ + + if ((s->flags & M_DISPLAY)) + state_attach_puts (_("[-- Begin signature " "information --]\n"), s); + for (idx = 0; (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) { + if (res == 1) + anybad = 1; + else if (res == 2) + anywarn = 1; + } + if (!anybad && idx && r_is_signed && *r_is_signed) + *r_is_signed = anywarn ? 2 : 1; /* Good signature. */ + + if ((s->flags & M_DISPLAY)) + state_attach_puts (_("[-- End signature " "information --]\n\n"), s); + } + gpgme_release (ctx); + ctx = NULL; fflush (fpout); rewind (fpout); tattach = mutt_read_mime_header (fpout, 0); - if (tattach) - { - /* - * Need to set the length of this body part. - */ - fstat (fileno (fpout), &info); - tattach->length = info.st_size - tattach->offset; - - tattach->warnsig = anywarn; + if (tattach) { + /* + * Need to set the length of this body part. + */ + fstat (fileno (fpout), &info); + tattach->length = info.st_size - tattach->offset; - /* See if we need to recurse on this MIME part. */ - mutt_parse_part (fpout, tattach); - } + tattach->warnsig = anywarn; + + /* See if we need to recurse on this MIME part. */ + mutt_parse_part (fpout, tattach); + } return tattach; } /* 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 pgp_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur) { char tempfile[_POSIX_PATH_MAX]; STATE s; BODY *first_part = b; int is_signed; - + first_part->goodsig = 0; first_part->warnsig = 0; - if(!mutt_is_multipart_encrypted(b)) + if (!mutt_is_multipart_encrypted (b)) return -1; - if(!b->parts || !b->parts->next) + if (!b->parts || !b->parts->next) return -1; - + b = b->parts->next; - + memset (&s, 0, sizeof (s)); s.fpin = fpin; mutt_mktemp (tempfile); - if (!(*fpout = safe_fopen (tempfile, "w+"))) - { + if (!(*fpout = safe_fopen (tempfile, "w+"))) { mutt_perror (tempfile); return -1; } @@ -1606,18 +1498,19 @@ int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) rewind (*fpout); if (is_signed > 0) first_part->goodsig = 1; - - return *cur? 0:-1; + + return *cur ? 0 : -1; } /* 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, BODY **cur) +int smime_gpgme_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, + BODY ** cur) { char tempfile[_POSIX_PATH_MAX]; STATE s; - FILE *tmpfp=NULL; + FILE *tmpfp = NULL; int is_signed; long saved_b_offset; size_t saved_b_length; @@ -1628,7 +1521,7 @@ int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) if (b->parts) return -1; - + /* Decode the body - we need to pass binary CMS to the backend. The backend allows for Base64 encoded data but it does not allow for QP which I have seen in some messages. So better @@ -1638,13 +1531,12 @@ int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) saved_b_length = b->length; memset (&s, 0, sizeof (s)); s.fpin = fpin; - fseek (s.fpin, b->offset, 0); + fseek (s.fpin, b->offset, 0); mutt_mktemp (tempfile); - if (!(tmpfp = safe_fopen (tempfile, "w+"))) - { - mutt_perror (tempfile); - return -1; - } + if (!(tmpfp = safe_fopen (tempfile, "w+"))) { + mutt_perror (tempfile); + return -1; + } mutt_unlink (tempfile); s.fpout = tmpfp; @@ -1658,11 +1550,10 @@ int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) s.fpin = tmpfp; s.fpout = 0; mutt_mktemp (tempfile); - if (!(*fpout = safe_fopen (tempfile, "w+"))) - { - mutt_perror (tempfile); - return -1; - } + if (!(*fpout = safe_fopen (tempfile, "w+"))) { + mutt_perror (tempfile); + return -1; + } mutt_unlink (tempfile); *cur = decrypt_part (b, &s, *fpout, 1, &is_signed); @@ -1673,65 +1564,63 @@ int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) b->offset = saved_b_offset; fclose (tmpfp); rewind (*fpout); - if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime (*cur)) - { - /* Assume that this is a opaque signed s/mime message. This is - an ugly way of doing it but we have anyway a problem with - arbitrary encoded S/MIME messages: Only the outer part may be - encrypted. The entire mime parsing should be revamped, - probably by keeping the temportary files so that we don't - need to decrypt them all the time. Inner parts of an - encrypted part can then pint into this file and tehre won't - never be a need to decrypt again. This needs a partial - rewrite of the MIME engine. */ - BODY *bb = *cur; - BODY *tmp_b; - - saved_b_type = bb->type; - saved_b_offset = bb->offset; - saved_b_length = bb->length; - memset (&s, 0, sizeof (s)); - s.fpin = *fpout; - fseek (s.fpin, bb->offset, 0); - mutt_mktemp (tempfile); - if (!(tmpfp = safe_fopen (tempfile, "w+"))) - { - mutt_perror (tempfile); - return -1; - } - mutt_unlink (tempfile); - - s.fpout = tmpfp; - mutt_decode_attachment (bb, &s); - fflush (tmpfp); - bb->length = ftell (s.fpout); - bb->offset = 0; - rewind (tmpfp); - fclose (*fpout); - - memset (&s, 0, sizeof (s)); - s.fpin = tmpfp; - s.fpout = 0; - mutt_mktemp (tempfile); - if (!(*fpout = safe_fopen (tempfile, "w+"))) - { - mutt_perror (tempfile); - return -1; - } - mutt_unlink (tempfile); - - tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed); - if (tmp_b) - tmp_b->goodsig = is_signed > 0; - bb->type = saved_b_type; - bb->length = saved_b_length; - bb->offset = saved_b_offset; - fclose (tmpfp); - rewind (*fpout); - mutt_free_body (cur); - *cur = tmp_b; + if (*cur && !is_signed && !(*cur)->parts + && mutt_is_application_smime (*cur)) { + /* Assume that this is a opaque signed s/mime message. This is + an ugly way of doing it but we have anyway a problem with + arbitrary encoded S/MIME messages: Only the outer part may be + encrypted. The entire mime parsing should be revamped, + probably by keeping the temportary files so that we don't + need to decrypt them all the time. Inner parts of an + encrypted part can then pint into this file and tehre won't + never be a need to decrypt again. This needs a partial + rewrite of the MIME engine. */ + BODY *bb = *cur; + BODY *tmp_b; + + saved_b_type = bb->type; + saved_b_offset = bb->offset; + saved_b_length = bb->length; + memset (&s, 0, sizeof (s)); + s.fpin = *fpout; + fseek (s.fpin, bb->offset, 0); + mutt_mktemp (tempfile); + if (!(tmpfp = safe_fopen (tempfile, "w+"))) { + mutt_perror (tempfile); + return -1; + } + mutt_unlink (tempfile); + + s.fpout = tmpfp; + mutt_decode_attachment (bb, &s); + fflush (tmpfp); + bb->length = ftell (s.fpout); + bb->offset = 0; + rewind (tmpfp); + fclose (*fpout); + + memset (&s, 0, sizeof (s)); + s.fpin = tmpfp; + s.fpout = 0; + mutt_mktemp (tempfile); + if (!(*fpout = safe_fopen (tempfile, "w+"))) { + mutt_perror (tempfile); + return -1; } - return *cur? 0:-1; + mutt_unlink (tempfile); + + tmp_b = decrypt_part (bb, &s, *fpout, 1, &is_signed); + if (tmp_b) + tmp_b->goodsig = is_signed > 0; + bb->type = saved_b_type; + bb->length = saved_b_length; + bb->offset = saved_b_offset; + fclose (tmpfp); + rewind (*fpout); + mutt_free_body (cur); + *cur = tmp_b; + } + return *cur ? 0 : -1; } @@ -1739,15 +1628,16 @@ int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) * Implementation of `pgp_check_traditional'. */ -static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only) +static int pgp_check_traditional_one_body (FILE * fp, BODY * b, + int tagged_only) { char tempfile[_POSIX_PATH_MAX]; char buf[HUGE_STRING]; FILE *tfp; - + short sgn = 0; short enc = 0; - + if (b->type != TYPETEXT) return 0; @@ -1755,26 +1645,22 @@ static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only) return 0; mutt_mktemp (tempfile); - if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0) - { + if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0) { unlink (tempfile); return 0; } - - if ((tfp = fopen (tempfile, "r")) == NULL) - { + + if ((tfp = fopen (tempfile, "r")) == NULL) { unlink (tempfile); return 0; } - - while (fgets (buf, sizeof (buf), tfp)) - { - if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15)) - { + + while (fgets (buf, sizeof (buf), tfp)) { + if (!safe_strncmp ("-----BEGIN PGP ", buf, 15)) { if (!mutt_strcmp ("MESSAGE-----\n", buf + 15)) - enc = 1; + enc = 1; else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15)) - sgn = 1; + sgn = 1; } } safe_fclose (&tfp); @@ -1784,28 +1670,27 @@ static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only) return 0; /* fix the content type */ - + mutt_set_parameter ("format", "fixed", &b->parameter); mutt_set_parameter ("x-action", enc ? "pgp-encrypted" : "pgp-signed", &b->parameter); - + return 1; } -int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int tagged_only) +int pgp_gpgme_check_traditional (FILE * fp, BODY * b, int tagged_only) { int rv = 0; int r; - for (; b; b = b->next) - { + + for (; b; b = b->next) { if (is_multipart (b)) rv = (pgp_gpgme_check_traditional (fp, b->parts, tagged_only) || rv); - else if (b->type == TYPETEXT) - { + else if (b->type == TYPETEXT) { if ((r = mutt_is_application_pgp (b))) - rv = (rv || r); + rv = (rv || r); else - rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv); + rv = (pgp_check_traditional_one_body (fp, b, tagged_only) || rv); } } return rv; @@ -1828,7 +1713,7 @@ int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int tagged_only) note that we can successfully handle anything produced by any existing versions of mutt.) */ -static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset) +static void copy_clearsigned (gpgme_data_t data, STATE * s, char *charset) { char buf[HUGE_STRING]; short complete, armor_header; @@ -1841,46 +1726,43 @@ static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset) return; unlink (fname); FREE (&fname); - + fc = fgetconv_open (fp, charset, Charset, M_ICONV_HOOK_FROM); - + for (complete = 1, armor_header = 1; fgetconvs (buf, sizeof (buf), fc) != NULL; - complete = strchr (buf, '\n') != NULL) - { - if (!complete) - { + complete = strchr (buf, '\n') != NULL) { + if (!complete) { if (!armor_header) - state_puts (buf, s); + state_puts (buf, s); continue; } if (!mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n")) break; - - if (armor_header) - { - if (buf[0] == '\n') - armor_header = 0; + + if (armor_header) { + if (buf[0] == '\n') + armor_header = 0; continue; } - - if (s->prefix) + + if (s->prefix) state_puts (s->prefix, s); - + if (buf[0] == '-' && buf[1] == ' ') state_puts (buf + 2, s); else state_puts (buf, s); } - + fgetconv_close (&fc); fclose (fp); } /* Support for classic_application/pgp */ -void pgp_gpgme_application_handler (BODY *m, STATE *s) +void pgp_gpgme_application_handler (BODY * m, STATE * s) { int needpass = -1, pgp_keyblock = 0; int clearsign = 0; @@ -1895,9 +1777,9 @@ void pgp_gpgme_application_handler (BODY *m, STATE *s) short maybe_goodsig = 1; short have_any_sigs = 0; - char body_charset[STRING]; /* Only used for clearsigned messages. */ + char body_charset[STRING]; /* Only used for clearsigned messages. */ - dprint (2, (debugfile, "Entering pgp_application_pgp handler\n")); + debug_print (2, ("Entering pgp_application_pgp handler\n")); /* For clearsigned messages we won't be able to get a character set but we know that this may only be text thus we assume Latin-1 @@ -1907,230 +1789,202 @@ void pgp_gpgme_application_handler (BODY *m, STATE *s) fseek (s->fpin, m->offset, 0); last_pos = m->offset; - - for (bytes = m->length; bytes > 0;) - { - if (fgets (buf, sizeof (buf), s->fpin) == NULL) - break; - - offset = ftell (s->fpin); - bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */ - last_pos = offset; - - if (!mutt_strncmp ("-----BEGIN PGP ", buf, 15)) - { - clearsign = 0; - start_pos = last_pos; - - if (!mutt_strcmp ("MESSAGE-----\n", buf + 15)) - needpass = 1; - else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15)) - { - clearsign = 1; - needpass = 0; - } - else if (!option (OPTDONTHANDLEPGPKEYS) && - !mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15)) - { - needpass = 0; - pgp_keyblock =1; - } - else - { - /* XXX - we may wish to recode here */ - if (s->prefix) - state_puts (s->prefix, s); - state_puts (buf, s); - continue; - } - - have_any_sigs = (have_any_sigs - || (clearsign && (s->flags & M_VERIFY))); - - /* Copy PGP material to an data container */ - armored_data = create_gpgme_data (); - gpgme_data_write (armored_data, buf, strlen (buf)); - while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) - { - offset = ftell (s->fpin); - bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf)*/ - last_pos = offset; - - gpgme_data_write (armored_data, buf, strlen (buf)); - - if ((needpass - && !mutt_strcmp ("-----END PGP MESSAGE-----\n", buf)) - || (!needpass - && (!mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) - || !mutt_strcmp ( - "-----END PGP PUBLIC KEY BLOCK-----\n",buf)))) - break; - } - - /* Invoke PGP if needed */ - if (!clearsign || (s->flags & M_VERIFY)) - { - unsigned int sig_stat = 0; - gpgme_data_t plaintext; - gpgme_ctx_t ctx; - - plaintext = create_gpgme_data (); - ctx = create_gpgme_context (0); - - if (clearsign) - err = gpgme_op_verify (ctx, armored_data, NULL, plaintext); - else - { - err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext); - if (gpg_err_code (err) == GPG_ERR_NO_DATA) - { - /* Decrypt verify can't handle signed only messages. */ - err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1) - ? gpgme_error_from_errno (errno) : 0; - /* Must release plaintext so that we supply an - uninitialized object. */ - gpgme_data_release (plaintext); - plaintext = create_gpgme_data (); - err = gpgme_op_verify (ctx, armored_data, - NULL, plaintext); - } - } - - if (err) - { - char errbuf[200]; - - snprintf (errbuf, sizeof(errbuf)-1, - _("Error: decryption/verification failed: %s\n"), - gpgme_strerror (err)); - state_attach_puts (errbuf, s); - } - else - { /* Decryption/Verification succeeded */ - char *tmpfname; - - { - /* Check wether signatures have been verified. */ - gpgme_verify_result_t verify_result; - - verify_result = gpgme_op_verify_result (ctx); - if (verify_result->signatures) - sig_stat = 1; - } - - have_any_sigs = 0; - maybe_goodsig = 0; - if ((s->flags & M_DISPLAY) && sig_stat) - { - int res, idx; - int anybad = 0; - int anywarn = 0; - - state_attach_puts (_("[-- Begin signature " - "information --]\n"), s); - have_any_sigs = 1; - for(idx=0; - (res = show_one_sig_status (ctx, idx, s)) != -1; - idx++) - { - if (res == 1) - anybad = 1; - else if (res == 2) - anywarn = 1; - } - if (!anybad && idx) - maybe_goodsig = 1; - - state_attach_puts (_("[-- End signature " - "information --]\n\n"), s); - } - - tmpfname = data_object_to_tempfile (plaintext, &pgpout); - if (!tmpfname) - { - pgpout = NULL; - state_attach_puts (_("Error: copy data failed\n"), s); - } - else - { - unlink (tmpfname); - FREE (&tmpfname); - } - } - gpgme_release (ctx); - } - - /* - * Now, copy cleartext to the screen. NOTE - we expect that PGP - * outputs utf-8 cleartext. This may not always be true, but it - * seems to be a reasonable guess. - */ - - if(s->flags & M_DISPLAY) - { - if (needpass) - state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s); - else if (pgp_keyblock) - state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), - s); - else - state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), - s); - } - - if (clearsign) - { - copy_clearsigned (armored_data, s, body_charset); - } - else if (pgpout) - { - FGETCONV *fc; - int c; - rewind (pgpout); - fc = fgetconv_open (pgpout, "utf-8", Charset, 0); - while ((c = fgetconv (fc)) != EOF) - { - state_putc (c, s); - if (c == '\n' && s->prefix) - state_puts (s->prefix, s); - } - fgetconv_close (&fc); - } - - if (s->flags & M_DISPLAY) - { - state_putc ('\n', s); - if (needpass) - state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s); - else if (pgp_keyblock) - state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s); - else - state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); - } - - if (pgpout) - { - safe_fclose (&pgpout); + + for (bytes = m->length; bytes > 0;) { + if (fgets (buf, sizeof (buf), s->fpin) == NULL) + break; + + offset = ftell (s->fpin); + bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */ + last_pos = offset; + + if (!safe_strncmp ("-----BEGIN PGP ", buf, 15)) { + clearsign = 0; + start_pos = last_pos; + + if (!mutt_strcmp ("MESSAGE-----\n", buf + 15)) + needpass = 1; + else if (!mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15)) { + clearsign = 1; + needpass = 0; + } + else if (!option (OPTDONTHANDLEPGPKEYS) && + !mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15)) { + needpass = 0; + pgp_keyblock = 1; + } + else { + /* XXX - we may wish to recode here */ + if (s->prefix) + state_puts (s->prefix, s); + state_puts (buf, s); + continue; + } + + have_any_sigs = (have_any_sigs || (clearsign && (s->flags & M_VERIFY))); + + /* Copy PGP material to an data container */ + armored_data = create_gpgme_data (); + gpgme_data_write (armored_data, buf, mutt_strlen (buf)); + while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) { + offset = ftell (s->fpin); + bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */ + last_pos = offset; + + gpgme_data_write (armored_data, buf, mutt_strlen (buf)); + + if ((needpass && !mutt_strcmp ("-----END PGP MESSAGE-----\n", buf)) + || (!needpass + && (!mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) + || !mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n", + buf)))) + break; + } + + /* Invoke PGP if needed */ + if (!clearsign || (s->flags & M_VERIFY)) { + unsigned int sig_stat = 0; + gpgme_data_t plaintext; + gpgme_ctx_t ctx; + + plaintext = create_gpgme_data (); + ctx = create_gpgme_context (0); + + if (clearsign) + err = gpgme_op_verify (ctx, armored_data, NULL, plaintext); + else { + err = gpgme_op_decrypt_verify (ctx, armored_data, plaintext); + if (gpg_err_code (err) == GPG_ERR_NO_DATA) { + /* Decrypt verify can't handle signed only messages. */ + err = (gpgme_data_seek (armored_data, 0, SEEK_SET) == -1) + ? gpgme_error_from_errno (errno) : 0; + /* Must release plaintext so that we supply an + uninitialized object. */ + gpgme_data_release (plaintext); + plaintext = create_gpgme_data (); + err = gpgme_op_verify (ctx, armored_data, NULL, plaintext); + } + } + + if (err) { + char errbuf[200]; + + snprintf (errbuf, sizeof (errbuf) - 1, + _("Error: decryption/verification failed: %s\n"), + gpgme_strerror (err)); + state_attach_puts (errbuf, s); + } + else { /* Decryption/Verification succeeded */ + char *tmpfname; + + { + /* Check wether signatures have been verified. */ + gpgme_verify_result_t verify_result; + + verify_result = gpgme_op_verify_result (ctx); + if (verify_result->signatures) + sig_stat = 1; + } + + have_any_sigs = 0; + maybe_goodsig = 0; + if ((s->flags & M_DISPLAY) && sig_stat) { + int res, idx; + int anybad = 0; + int anywarn = 0; + + state_attach_puts (_("[-- Begin signature " + "information --]\n"), s); + have_any_sigs = 1; + for (idx = 0; + (res = show_one_sig_status (ctx, idx, s)) != -1; idx++) { + if (res == 1) + anybad = 1; + else if (res == 2) + anywarn = 1; } + if (!anybad && idx) + maybe_goodsig = 1; + + state_attach_puts (_("[-- End signature " + "information --]\n\n"), s); + } + + tmpfname = data_object_to_tempfile (plaintext, &pgpout); + if (!tmpfname) { + pgpout = NULL; + state_attach_puts (_("Error: copy data failed\n"), s); + } + else { + unlink (tmpfname); + FREE (&tmpfname); + } } - else - { - /* XXX - we may wish to recode here */ - if (s->prefix) + gpgme_release (ctx); + } + + /* + * Now, copy cleartext to the screen. NOTE - we expect that PGP + * outputs utf-8 cleartext. This may not always be true, but it + * seems to be a reasonable guess. + */ + + if (s->flags & M_DISPLAY) { + if (needpass) + state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s); + else if (pgp_keyblock) + state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s); + else + state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s); + } + + if (clearsign) { + copy_clearsigned (armored_data, s, body_charset); + } + else if (pgpout) { + FGETCONV *fc; + int c; + + rewind (pgpout); + fc = fgetconv_open (pgpout, "utf-8", Charset, 0); + while ((c = fgetconv (fc)) != EOF) { + state_putc (c, s); + if (c == '\n' && s->prefix) state_puts (s->prefix, s); - state_puts (buf, s); } + fgetconv_close (&fc); + } + + if (s->flags & M_DISPLAY) { + state_putc ('\n', s); + if (needpass) + state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s); + else if (pgp_keyblock) + state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s); + else + state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s); + } + + if (pgpout) { + safe_fclose (&pgpout); + } + } + else { + /* XXX - we may wish to recode here */ + if (s->prefix) + state_puts (s->prefix, s); + state_puts (buf, s); } + } m->goodsig = (maybe_goodsig && have_any_sigs); - - if (needpass == -1) - { - state_attach_puts (_("[-- Error: could not find beginning" - " of PGP message! --]\n\n"), s); - return; - } - dprint (2, (debugfile, "Leaving pgp_application_pgp handler\n")); + + if (needpass == -1) { + state_attach_puts (_("[-- Error: could not find beginning" + " of PGP message! --]\n\n"), s); + return; + } + debug_print (2, ("Leaving pgp_application_pgp handler\n")); } /* @@ -2138,84 +1992,84 @@ void pgp_gpgme_application_handler (BODY *m, STATE *s) */ /* MIME handler for pgp/mime encrypted messages. */ -void pgp_gpgme_encrypted_handler (BODY *a, STATE *s) +void pgp_gpgme_encrypted_handler (BODY * a, STATE * s) { char tempfile[_POSIX_PATH_MAX]; FILE *fpout; BODY *tattach; BODY *orig_body = a; int is_signed; - - dprint (2, (debugfile, "Entering pgp_encrypted handler\n")); + + debug_print (2, ("Entering pgp_encrypted handler\n")); a = a->parts; if (!a || a->type != TYPEAPPLICATION || !a->subtype - || ascii_strcasecmp ("pgp-encrypted", a->subtype) + || ascii_strcasecmp ("pgp-encrypted", a->subtype) || !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype - || ascii_strcasecmp ("octet-stream", a->next->subtype) ) - { - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"), - s); - return; - } + || ascii_strcasecmp ("octet-stream", a->next->subtype)) { + if (s->flags & M_DISPLAY) + state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"), + s); + return; + } /* Move forward to the application/pgp-encrypted body. */ a = a->next; mutt_mktemp (tempfile); - if (!(fpout = safe_fopen (tempfile, "w+"))) - { - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: could not create temporary file! " - "--]\n"), s); - return; - } + if (!(fpout = safe_fopen (tempfile, "w+"))) { + if (s->flags & M_DISPLAY) + state_attach_puts (_("[-- Error: could not create temporary file! " + "--]\n"), s); + return; + } tattach = decrypt_part (a, s, fpout, 0, &is_signed); - if (tattach) + if (tattach) { + tattach->goodsig = is_signed > 0; + + if (s->flags & M_DISPLAY) + state_attach_puts (is_signed ? + _ + ("[-- The following data is PGP/MIME signed and encrypted --]\n\n") + : + _ + ("[-- The following data is PGP/MIME encrypted --]\n\n"), + s); + { - tattach->goodsig = is_signed > 0; - - if (s->flags & M_DISPLAY) - state_attach_puts (is_signed? - _("[-- The following data is PGP/MIME signed and encrypted --]\n\n"): - _("[-- The following data is PGP/MIME encrypted --]\n\n"), - s); - - { - FILE *savefp = s->fpin; - s->fpin = fpout; - mutt_body_handler (tattach, s); - s->fpin = savefp; - } + FILE *savefp = s->fpin; - /* - * if a multipart/signed is the _only_ sub-part of a - * multipart/encrypted, cache signature verification - * status. - */ - if (mutt_is_multipart_signed (tattach) && !tattach->next) - orig_body->goodsig |= tattach->goodsig; - - if (s->flags & M_DISPLAY) - { - state_puts ("\n", s); - state_attach_puts (is_signed? - _("[-- End of PGP/MIME signed and encrypted data --]\n"): - _("[-- End of PGP/MIME encrypted data --]\n"), - s); - } + s->fpin = fpout; + mutt_body_handler (tattach, s); + s->fpin = savefp; + } - mutt_free_body (&tattach); + /* + * if a multipart/signed is the _only_ sub-part of a + * multipart/encrypted, cache signature verification + * status. + */ + if (mutt_is_multipart_signed (tattach) && !tattach->next) + orig_body->goodsig |= tattach->goodsig; + + if (s->flags & M_DISPLAY) { + state_puts ("\n", s); + state_attach_puts (is_signed ? + _ + ("[-- End of PGP/MIME signed and encrypted data --]\n") + : _("[-- End of PGP/MIME encrypted data --]\n"), s); } - + + mutt_free_body (&tattach); + } + fclose (fpout); - mutt_unlink(tempfile); - dprint (2, (debugfile, "Leaving pgp_encrypted handler\n")); + mutt_unlink (tempfile); + debug_print (2, ("Leaving pgp_encrypted handler\n")); } /* Support for application/smime */ -void smime_gpgme_application_handler (BODY *a, STATE *s) +void smime_gpgme_application_handler (BODY * a, STATE * s) { char tempfile[_POSIX_PATH_MAX]; FILE *fpout; @@ -2223,67 +2077,64 @@ void smime_gpgme_application_handler (BODY *a, STATE *s) int is_signed; - dprint (2, (debugfile, "Entering smime_encrypted handler\n")); - + debug_print (2, ("Entering smime_encrypted handler\n")); + a->warnsig = 0; mutt_mktemp (tempfile); - if (!(fpout = safe_fopen (tempfile, "w+"))) - { - if (s->flags & M_DISPLAY) - state_attach_puts (_("[-- Error: could not create temporary file! " - "--]\n"), s); - return; - } + if (!(fpout = safe_fopen (tempfile, "w+"))) { + if (s->flags & M_DISPLAY) + state_attach_puts (_("[-- Error: could not create temporary file! " + "--]\n"), s); + return; + } tattach = decrypt_part (a, s, fpout, 1, &is_signed); - if (tattach) + if (tattach) { + tattach->goodsig = is_signed > 0; + + if (s->flags & M_DISPLAY) + state_attach_puts (is_signed ? + _("[-- The following data is S/MIME signed --]\n\n") + : + _ + ("[-- The following data is S/MIME encrypted --]\n\n"), + s); + { - tattach->goodsig = is_signed > 0; - - if (s->flags & M_DISPLAY) - state_attach_puts (is_signed? - _("[-- The following data is S/MIME signed --]\n\n"): - _("[-- The following data is S/MIME encrypted --]\n\n"), - s); - - { - FILE *savefp = s->fpin; - s->fpin = fpout; - mutt_body_handler (tattach, s); - s->fpin = savefp; - } + FILE *savefp = s->fpin; - /* - * if a multipart/signed is the _only_ sub-part of a - * multipart/encrypted, cache signature verification - * status. - */ - if (mutt_is_multipart_signed (tattach) && !tattach->next) - { - if (!(a->goodsig = tattach->goodsig)) - a->warnsig = tattach->warnsig; - } - else if (tattach->goodsig) - { - a->goodsig = 1; - a->warnsig = tattach->warnsig; - } + s->fpin = fpout; + mutt_body_handler (tattach, s); + s->fpin = savefp; + } - if (s->flags & M_DISPLAY) - { - state_puts ("\n", s); - state_attach_puts (is_signed? - _("[-- End of S/MIME signed data --]\n"): - _("[-- End of S/MIME encrypted data --]\n"), - s); - } + /* + * if a multipart/signed is the _only_ sub-part of a + * multipart/encrypted, cache signature verification + * status. + */ + if (mutt_is_multipart_signed (tattach) && !tattach->next) { + if (!(a->goodsig = tattach->goodsig)) + a->warnsig = tattach->warnsig; + } + else if (tattach->goodsig) { + a->goodsig = 1; + a->warnsig = tattach->warnsig; + } - mutt_free_body (&tattach); + if (s->flags & M_DISPLAY) { + state_puts ("\n", s); + state_attach_puts (is_signed ? + _("[-- End of S/MIME signed data --]\n") : + _("[-- End of S/MIME encrypted data --]\n"), s); } - + + mutt_free_body (&tattach); + } + fclose (fpout); - mutt_unlink(tempfile); - dprint (2, (debugfile, "Leaving smime_encrypted handler\n")); + mutt_unlink (tempfile); + debug_print (2, ("Leaving smime_encrypted handler\n")); } @@ -2309,8 +2160,7 @@ static const char *crypt_entry_fmt (char *dest, const char *prefix, const char *ifstring, const char *elsestring, - unsigned long data, - format_flag flags) + unsigned long data, format_flag flags) { char fmt[16]; crypt_entry_t *entry; @@ -2321,190 +2171,174 @@ static const char *crypt_entry_fmt (char *dest, unsigned long val; entry = (crypt_entry_t *) data; - key = entry->key; + key = entry->key; /* if (isupper ((unsigned char) op)) */ /* key = pkey; */ - kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS) - | uid->flags*/); - - switch (ascii_tolower (op)) + kflags = (key->flags /*| (pkey->flags & KEYFLAG_RESTRICTIONS) + | uid->flags */ ); + + switch (ascii_tolower (op)) { + case '[': { - case '[': - { - const char *cp; - char buf2[SHORT_STRING], *p; - int do_locales; - struct tm *tm; - size_t len; - - p = dest; - - cp = src; - if (*cp == '!') - { - do_locales = 0; - cp++; - } - else - do_locales = 1; - - len = destlen - 1; - while (len > 0 && *cp != ']') - { - if (*cp == '%') - { - cp++; - if (len >= 2) - { - *p++ = '%'; - *p++ = *cp; - len -= 2; - } - else - break; /* not enough space */ - cp++; - } - else - { - *p++ = *cp++; - len--; - } - } - *p = 0; - - if (do_locales && Locale) - setlocale (LC_TIME, Locale); - - { - time_t tt = 0; - - if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0)) - tt = key->kobj->subkeys->timestamp; - - tm = localtime (&tt); - } - strftime (buf2, sizeof (buf2), dest, tm); - - if (do_locales) - setlocale (LC_TIME, "C"); - - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, buf2); - if (len > 0) - src = cp + 1; - } - break; - case 'n': - if (!optional) - { - snprintf (fmt, sizeof (fmt), "%%%sd", prefix); - snprintf (dest, destlen, fmt, entry->num); - } - break; - case 'k': - if (!optional) - { - /* fixme: we need a way to distinguish between main and subkeys. - Store the idx in entry? */ - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, crypt_keyid (key)); - } - break; - case 'u': - if (!optional) - { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, key->uid); - } - break; - case 'a': - if (!optional) - { - snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix); - if (key->kobj->subkeys) - s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo); - else - s = "?"; - snprintf (dest, destlen, fmt, s); - } - break; - case 'l': - if (!optional) - { - snprintf (fmt, sizeof (fmt), "%%%slu", prefix); - if (key->kobj->subkeys) - val = key->kobj->subkeys->length; - else - val = 0; - snprintf (dest, destlen, fmt, val); + const char *cp; + char buf2[SHORT_STRING], *p; + int do_locales; + struct tm *tm; + size_t len; + + p = dest; + + cp = src; + if (*cp == '!') { + do_locales = 0; + cp++; } - break; - case 'f': - if (!optional) - { - snprintf (fmt, sizeof (fmt), "%%%sc", prefix); - snprintf (dest, destlen, fmt, crypt_flags (kflags)); + else + do_locales = 1; + + len = destlen - 1; + while (len > 0 && *cp != ']') { + if (*cp == '%') { + cp++; + if (len >= 2) { + *p++ = '%'; + *p++ = *cp; + len -= 2; + } + else + break; /* not enough space */ + cp++; + } + else { + *p++ = *cp++; + len--; + } } - else if (!(kflags & (KEYFLAG_RESTRICTIONS))) - optional = 0; - break; - case 'c': - if (!optional) + *p = 0; + + if (do_locales && Locale) + setlocale (LC_TIME, Locale); + { - snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, crypt_key_abilities (kflags)); + time_t tt = 0; + + if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0)) + tt = key->kobj->subkeys->timestamp; + + tm = localtime (&tt); } - else if (!(kflags & (KEYFLAG_ABILITIES))) - optional = 0; - break; - case 't': - if ((kflags & KEYFLAG_ISX509)) - s = "x"; + strftime (buf2, sizeof (buf2), dest, tm); + + if (do_locales) + setlocale (LC_TIME, "C"); + + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, buf2); + if (len > 0) + src = cp + 1; + } + break; + case 'n': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, entry->num); + } + break; + case 'k': + if (!optional) { + /* fixme: we need a way to distinguish between main and subkeys. + Store the idx in entry? */ + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, crypt_keyid (key)); + } + break; + case 'u': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, key->uid); + } + break; + case 'a': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%s.3s", prefix); + if (key->kobj->subkeys) + s = gpgme_pubkey_algo_name (key->kobj->subkeys->pubkey_algo); else - { - gpgme_user_id_t uid = NULL; - unsigned int i = 0; - - for (i = 0, uid = key->kobj->uids; uid && (i < key->idx); - i++, uid = uid->next) - ; - if (uid) - switch (uid->validity) - { - case GPGME_VALIDITY_UNDEFINED: - s = "q"; - break; - case GPGME_VALIDITY_NEVER: - s = "n"; - break; - case GPGME_VALIDITY_MARGINAL: - s = "m"; - break; - case GPGME_VALIDITY_FULL: - s = "f"; - break; - case GPGME_VALIDITY_ULTIMATE: - s = "u"; - break; - case GPGME_VALIDITY_UNKNOWN: - default: - s = "?"; - break; - } - } + s = "?"; + snprintf (dest, destlen, fmt, s); + } + break; + case 'l': + if (!optional) { + snprintf (fmt, sizeof (fmt), "%%%slu", prefix); + if (key->kobj->subkeys) + val = key->kobj->subkeys->length; + else + val = 0; + snprintf (dest, destlen, fmt, val); + } + break; + case 'f': + if (!optional) { snprintf (fmt, sizeof (fmt), "%%%sc", prefix); - snprintf (dest, destlen, fmt, s? *s: 'B'); - break; - case 'p': + snprintf (dest, destlen, fmt, crypt_flags (kflags)); + } + else if (!(kflags & (KEYFLAG_RESTRICTIONS))) + optional = 0; + break; + case 'c': + if (!optional) { snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (dest, destlen, fmt, - gpgme_get_protocol_name (key->kobj->protocol)); - break; + snprintf (dest, destlen, fmt, crypt_key_abilities (kflags)); + } + else if (!(kflags & (KEYFLAG_ABILITIES))) + optional = 0; + break; + case 't': + if ((kflags & KEYFLAG_ISX509)) + s = "x"; + else { + gpgme_user_id_t uid = NULL; + unsigned int i = 0; + + for (i = 0, uid = key->kobj->uids; uid && (i < key->idx); + i++, uid = uid->next); + if (uid) + switch (uid->validity) { + case GPGME_VALIDITY_UNDEFINED: + s = "q"; + break; + case GPGME_VALIDITY_NEVER: + s = "n"; + break; + case GPGME_VALIDITY_MARGINAL: + s = "m"; + break; + case GPGME_VALIDITY_FULL: + s = "f"; + break; + case GPGME_VALIDITY_ULTIMATE: + s = "u"; + break; + case GPGME_VALIDITY_UNKNOWN: + default: + s = "?"; + break; + } + } + snprintf (fmt, sizeof (fmt), "%%%sc", prefix); + snprintf (dest, destlen, fmt, s ? *s : 'B'); + break; + case 'p': + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, + gpgme_get_protocol_name (key->kobj->protocol)); + break; - default: - *dest = '\0'; + default: + *dest = '\0'; } if (optional) @@ -2513,18 +2347,18 @@ static const char *crypt_entry_fmt (char *dest, mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0); return (src); } - + /* Used by the display fucntion to format a line. */ static void crypt_entry (char *s, size_t l, MUTTMENU * menu, int num) { crypt_key_t **key_table = (crypt_key_t **) menu->data; crypt_entry_t entry; - + entry.key = key_table[num]; entry.num = num + 1; - mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt, - (unsigned long) &entry, M_FORMAT_ARROWCURSOR); + mutt_FormatString (s, l, NONULL (PgpEntryFormat), crypt_entry_fmt, + (unsigned long) &entry, M_FORMAT_ARROWCURSOR); } /* Compare two addresses and the keyid to be used for sorting. */ @@ -2534,16 +2368,16 @@ static int _crypt_compare_address (const void *a, const void *b) crypt_key_t **t = (crypt_key_t **) b; int r; - if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid))) + if ((r = safe_strcasecmp ((*s)->uid, (*t)->uid))) return r > 0; else - return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0; + return safe_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0; } static int crypt_compare_address (const void *a, const void *b) { return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_address (a, b) - : _crypt_compare_address (a, b)); + : _crypt_compare_address (a, b)); } @@ -2554,16 +2388,16 @@ static int _crypt_compare_keyid (const void *a, const void *b) crypt_key_t **t = (crypt_key_t **) b; int r; - if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)))) + if ((r = safe_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)))) return r > 0; else - return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0; + return safe_strcasecmp ((*s)->uid, (*t)->uid) > 0; } static int crypt_compare_keyid (const void *a, const void *b) { return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_keyid (a, b) - : _crypt_compare_keyid (a, b)); + : _crypt_compare_keyid (a, b)); } /* Compare 2 creation dates and the addresses. For sorting. */ @@ -2583,13 +2417,13 @@ static int _crypt_compare_date (const void *a, const void *b) if (ts < tt) return 0; - return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0; + return safe_strcasecmp ((*s)->uid, (*t)->uid) > 0; } static int crypt_compare_date (const void *a, const void *b) { return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_date (a, b) - : _crypt_compare_date (a, b)); + : _crypt_compare_date (a, b)); } /* Compare two trust values, the key length, the creation dates. the @@ -2602,7 +2436,7 @@ static int _crypt_compare_trust (const void *a, const void *b) int r; if ((r = (((*s)->flags & (KEYFLAG_RESTRICTIONS)) - - ((*t)->flags & (KEYFLAG_RESTRICTIONS))))) + - ((*t)->flags & (KEYFLAG_RESTRICTIONS))))) return r > 0; if ((*s)->kobj->uids) @@ -2628,160 +2462,143 @@ static int _crypt_compare_trust (const void *a, const void *b) if (ts < tt) return 0; - if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid))) + if ((r = safe_strcasecmp ((*s)->uid, (*t)->uid))) return r > 0; - return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0; + return (safe_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0; } static int crypt_compare_trust (const void *a, const void *b) { return ((PgpSortKeys & SORT_REVERSE) ? !_crypt_compare_trust (a, b) - : _crypt_compare_trust (a, b)); + : _crypt_compare_trust (a, b)); } /* Print the X.500 Distinguished Name part KEY from the array of parts DN to FP. */ -static int -print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) +static int print_dn_part (FILE * fp, struct dn_array_s *dn, const char *key) { int any = 0; - for (; dn->key; dn++) - { - if (!strcmp (dn->key, key)) - { - if (any) - fputs (" + ", fp); - print_utf8 (fp, dn->value, strlen (dn->value)); - any = 1; - } + for (; dn->key; dn++) { + if (!mutt_strcmp (dn->key, key)) { + if (any) + fputs (" + ", fp); + print_utf8 (fp, dn->value, mutt_strlen (dn->value)); + any = 1; } + } return any; } /* Print all parts of a DN in a standard sequence. */ -static void -print_dn_parts (FILE *fp, struct dn_array_s *dn) +static void print_dn_parts (FILE * fp, struct dn_array_s *dn) { const char *stdpart[] = { - "CN", "OU", "O", "STREET", "L", "ST", "C", NULL + "CN", "OU", "O", "STREET", "L", "ST", "C", NULL }; - int any=0, any2=0, i; - - for (i=0; stdpart[i]; i++) - { + int any = 0, any2 = 0, i; + + for (i = 0; stdpart[i]; i++) { + if (any) + fputs (", ", fp); + any = print_dn_part (fp, dn, stdpart[i]); + } + /* now print the rest without any specific ordering */ + for (; dn->key; dn++) { + for (i = 0; stdpart[i]; i++) { + if (!mutt_strcmp (dn->key, stdpart[i])) + break; + } + if (!stdpart[i]) { if (any) fputs (", ", fp); - any = print_dn_part (fp, dn, stdpart[i]); - } - /* now print the rest without any specific ordering */ - for (; dn->key; dn++) - { - for (i=0; stdpart[i]; i++) - { - if (!strcmp (dn->key, stdpart[i])) - break; - } - if (!stdpart[i]) - { - if (any) - fputs (", ", fp); - if (!any2) - fputs ("(", fp); - any = print_dn_part (fp, dn, dn->key); - any2 = 1; - } + if (!any2) + fputs ("(", fp); + any = print_dn_part (fp, dn, dn->key); + any2 = 1; } + } if (any2) fputs (")", fp); } /* Parse an RDN; this is a helper to parse_dn(). */ -static const unsigned char * -parse_dn_part (struct dn_array_s *array, const unsigned char *string) +static const unsigned char *parse_dn_part (struct dn_array_s *array, + const unsigned char *string) { const unsigned char *s, *s1; size_t n; unsigned char *p; /* parse attributeType */ - for (s = string+1; *s && *s != '='; s++) - ; + for (s = string + 1; *s && *s != '='; s++); if (!*s) - return NULL; /* error */ + return NULL; /* error */ n = s - string; if (!n) - return NULL; /* empty key */ - array->key = safe_malloc (n+1); - p = (unsigned char *)array->key; - memcpy (p, string, n); /* fixme: trim trailing spaces */ + return NULL; /* empty key */ + array->key = safe_malloc (n + 1); + p = (unsigned char *) array->key; + memcpy (p, string, n); /* fixme: trim trailing spaces */ p[n] = 0; string = s + 1; - if (*string == '#') - { /* hexstring */ - string++; - for (s=string; hexdigitp (s); s++) + if (*string == '#') { /* hexstring */ + string++; + for (s = string; hexdigitp (s); s++) + s++; + n = s - string; + if (!n || (n & 1)) + return NULL; /* empty or odd number of digits */ + n /= 2; + p = safe_malloc (n + 1); + array->value = (char *) p; + for (s1 = string; n; s1 += 2, n--) + *p++ = xtoi_2 (s1); + *p = 0; + } + else { /* regular v3 quoted string */ + for (n = 0, s = string; *s; s++) { + if (*s == '\\') { /* pair */ s++; - n = s - string; - if (!n || (n & 1)) - return NULL; /* empty or odd number of digits */ - n /= 2; - p = safe_malloc (n+1); - array->value = (char*)p; - for (s1=string; n; s1 += 2, n--) - *p++ = xtoi_2 (s1); - *p = 0; - } - else - { /* regular v3 quoted string */ - for (n=0, s=string; *s; s++) - { - if (*s == '\\') - { /* pair */ - s++; - if (*s == ',' || *s == '=' || *s == '+' - || *s == '<' || *s == '>' || *s == '#' || *s == ';' - || *s == '\\' || *s == '\"' || *s == ' ') - n++; - else if (hexdigitp (s) && hexdigitp (s+1)) - { - s++; - n++; - } - else - return NULL; /* invalid escape sequence */ - } - else if (*s == '\"') - return NULL; /* invalid encoding */ - else if (*s == ',' || *s == '=' || *s == '+' - || *s == '<' || *s == '>' || *s == '#' || *s == ';' ) - break; - else - n++; + if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' + || *s == '\\' || *s == '\"' || *s == ' ') + n++; + else if (hexdigitp (s) && hexdigitp (s + 1)) { + s++; + n++; } + else + return NULL; /* invalid escape sequence */ + } + else if (*s == '\"') + return NULL; /* invalid encoding */ + else if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';') + break; + else + n++; + } - p = safe_malloc (n+1); - array->value = (char*)p; - for (s=string; n; s++, n--) - { - if (*s == '\\') - { - s++; - if (hexdigitp (s)) - { - *p++ = xtoi_2 (s); - s++; - } - else - *p++ = *s; - } - else - *p++ = *s; + p = safe_malloc (n + 1); + array->value = (char *) p; + for (s = string; n; s++, n--) { + if (*s == '\\') { + s++; + if (hexdigitp (s)) { + *p++ = xtoi_2 (s); + s++; } - *p = 0; + else + *p++ = *s; + } + else + *p++ = *s; } + *p = 0; + } return s; } @@ -2789,59 +2606,54 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) /* Parse a DN and return an array-ized one. This is not a validating parser and it does not support any old-stylish syntax; gpgme is expected to return only rfc2253 compatible strings. */ -static struct dn_array_s * -parse_dn (const unsigned char *string) +static struct dn_array_s *parse_dn (const unsigned char *string) { struct dn_array_s *array; size_t arrayidx, arraysize; int i; - arraysize = 7; /* C,ST,L,O,OU,CN,email */ - array = safe_malloc ((arraysize+1) * sizeof *array); + arraysize = 7; /* C,ST,L,O,OU,CN,email */ + array = safe_malloc ((arraysize + 1) * sizeof *array); arrayidx = 0; - while (*string) - { - while (*string == ' ') - string++; - if (!*string) - break; /* ready */ - if (arrayidx >= arraysize) - { /* mutt lacks a real safe_realoc - so we need to copy */ - struct dn_array_s *a2; - - arraysize += 5; - a2 = safe_malloc ((arraysize+1) * sizeof *array); - for (i=0; i < arrayidx; i++) - { - a2[i].key = array[i].key; - a2[i].value = array[i].value; - } - FREE (&array); - array = a2; - } - array[arrayidx].key = NULL; - array[arrayidx].value = NULL; - string = parse_dn_part (array+arrayidx, string); - arrayidx++; - if (!string) - goto failure; - while (*string == ' ') - string++; - if (*string && *string != ',' && *string != ';' && *string != '+') - goto failure; /* invalid delimiter */ - if (*string) - string++; - } + while (*string) { + while (*string == ' ') + string++; + if (!*string) + break; /* ready */ + if (arrayidx >= arraysize) { /* mutt lacks a real safe_realoc - so we need to copy */ + struct dn_array_s *a2; + + arraysize += 5; + a2 = safe_malloc ((arraysize + 1) * sizeof *array); + for (i = 0; i < arrayidx; i++) { + a2[i].key = array[i].key; + a2[i].value = array[i].value; + } + FREE (&array); + array = a2; + } + array[arrayidx].key = NULL; + array[arrayidx].value = NULL; + string = parse_dn_part (array + arrayidx, string); + arrayidx++; + if (!string) + goto failure; + while (*string == ' ') + string++; + if (*string && *string != ',' && *string != ';' && *string != '+') + goto failure; /* invalid delimiter */ + if (*string) + string++; + } array[arrayidx].key = NULL; array[arrayidx].value = NULL; return array; - failure: - for (i=0; i < arrayidx; i++) - { - FREE (&array[i].key); - FREE (&array[i].value); - } +failure: + for (i = 0; i < arrayidx; i++) { + FREE (&array[i].key); + FREE (&array[i].value); + } FREE (&array); return NULL; } @@ -2851,82 +2663,74 @@ parse_dn (const unsigned char *string) displayed in a proper way, which does mean to reorder some parts for S/MIME's DNs. USERID is a string as returned by the gpgme key functions. It is utf-8 encoded. */ -static void -parse_and_print_user_id (FILE *fp, const char *userid) +static void parse_and_print_user_id (FILE * fp, const char *userid) { const char *s; int i; - if (*userid == '<') - { - s = strchr (userid+1, '>'); - if (s) - print_utf8 (fp, userid+1, s-userid-1); - } + if (*userid == '<') { + s = strchr (userid + 1, '>'); + if (s) + print_utf8 (fp, userid + 1, s - userid - 1); + } else if (*userid == '(') fputs (_("[Can't display this user ID (unknown encoding)]"), fp); - else if (!digit_or_letter ((const unsigned char *)userid)) + else if (!digit_or_letter ((const unsigned char *) userid)) fputs (_("[Can't display this user ID (invalid encoding)]"), fp); - else - { - struct dn_array_s *dn = parse_dn ((const unsigned char *)userid); - if (!dn) - fputs (_("[Can't display this user ID (invalid DN)]"), fp); - else - { - print_dn_parts (fp, dn); - for (i=0; dn[i].key; i++) - { - FREE (&dn[i].key); - FREE (&dn[i].value); - } - FREE (&dn); - } + else { + struct dn_array_s *dn = parse_dn ((const unsigned char *) userid); + + if (!dn) + fputs (_("[Can't display this user ID (invalid DN)]"), fp); + else { + print_dn_parts (fp, dn); + for (i = 0; dn[i].key; i++) { + FREE (&dn[i].key); + FREE (&dn[i].value); + } + FREE (&dn); } + } } -typedef enum - { - KEY_CAP_CAN_ENCRYPT, - KEY_CAP_CAN_SIGN, - KEY_CAP_CAN_CERTIFY - } -key_cap_t; +typedef enum { + KEY_CAP_CAN_ENCRYPT, + KEY_CAP_CAN_SIGN, + KEY_CAP_CAN_CERTIFY +} key_cap_t; -static unsigned int -key_check_cap (gpgme_key_t key, key_cap_t cap) +static unsigned int key_check_cap (gpgme_key_t key, key_cap_t cap) { gpgme_subkey_t subkey = NULL; unsigned int ret = 0; - switch (cap) - { - case KEY_CAP_CAN_ENCRYPT: - if (! (ret = key->can_encrypt)) - for (subkey = key->subkeys; subkey; subkey = subkey->next) - if ((ret = subkey->can_encrypt)) - break; - break; - case KEY_CAP_CAN_SIGN: - if (! (ret = key->can_sign)) - for (subkey = key->subkeys; subkey; subkey = subkey->next) - if ((ret = subkey->can_sign)) - break; - break; - case KEY_CAP_CAN_CERTIFY: - if (! (ret = key->can_certify)) - for (subkey = key->subkeys; subkey; subkey = subkey->next) - if ((ret = subkey->can_certify)) - break; - break; - } + switch (cap) { + case KEY_CAP_CAN_ENCRYPT: + if (!(ret = key->can_encrypt)) + for (subkey = key->subkeys; subkey; subkey = subkey->next) + if ((ret = subkey->can_encrypt)) + break; + break; + case KEY_CAP_CAN_SIGN: + if (!(ret = key->can_sign)) + for (subkey = key->subkeys; subkey; subkey = subkey->next) + if ((ret = subkey->can_sign)) + break; + break; + case KEY_CAP_CAN_CERTIFY: + if (!(ret = key->can_certify)) + for (subkey = key->subkeys; subkey; subkey = subkey->next) + if ((ret = subkey->can_certify)) + break; + break; + } return ret; } /* Print verbose information about a key or certificate to FP. */ -static void print_key_info (gpgme_key_t key, FILE *fp) +static void print_key_info (gpgme_key_t key, FILE * fp) { int idx; const char *s = NULL, *s2 = NULL; @@ -2944,50 +2748,46 @@ static void print_key_info (gpgme_key_t key, FILE *fp) is_pgp = key->protocol == GPGME_PROTOCOL_OpenPGP; - for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) - { - if (uid->revoked) - continue; + for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) { + if (uid->revoked) + continue; - s = uid->uid; - fprintf (fp, "%s ......: ", idx ? _(" aka") :_("Name")); - if (uid->invalid) - { - fputs (_("[Invalid]"), fp); - putc (' ', fp); - } - if (is_pgp) - print_utf8 (fp, s, strlen(s)); - else - parse_and_print_user_id (fp, s); - putc ('\n', fp); + s = uid->uid; + fprintf (fp, "%s ......: ", idx ? _(" aka") : _("Name")); + if (uid->invalid) { + fputs (_("[Invalid]"), fp); + putc (' ', fp); } + if (is_pgp) + print_utf8 (fp, s, mutt_strlen (s)); + else + parse_and_print_user_id (fp, s); + putc ('\n', fp); + } - if (key->subkeys && (key->subkeys->timestamp > 0)) - { - tt = key->subkeys->timestamp; + if (key->subkeys && (key->subkeys->timestamp > 0)) { + tt = key->subkeys->timestamp; - tm = localtime (&tt); + tm = localtime (&tt); #ifdef HAVE_LANGINFO_D_T_FMT - strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); + strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); #else - strftime (shortbuf, sizeof shortbuf, "%c", tm); + strftime (shortbuf, sizeof shortbuf, "%c", tm); #endif - fprintf (fp, "Valid From : %s\n", shortbuf); - } - - if (key->subkeys && (key->subkeys->expires > 0)) - { - tt = key->subkeys->expires; - - tm = localtime (&tt); + fprintf (fp, "Valid From : %s\n", shortbuf); + } + + if (key->subkeys && (key->subkeys->expires > 0)) { + tt = key->subkeys->expires; + + tm = localtime (&tt); #ifdef HAVE_LANGINFO_D_T_FMT - strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); + strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); #else - strftime (shortbuf, sizeof shortbuf, "%c", tm); + strftime (shortbuf, sizeof shortbuf, "%c", tm); #endif - fprintf (fp, "Valid To ..: %s\n", shortbuf); - } + fprintf (fp, "Valid To ..: %s\n", shortbuf); + } if (key->subkeys) s = gpgme_pubkey_algo_name (key->subkeys->pubkey_algo); @@ -3004,167 +2804,144 @@ static void print_key_info (gpgme_key_t key, FILE *fp) fprintf (fp, "Key Usage .: "); delim = ""; - if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) - { - fprintf (fp, "%s%s", delim, _("encryption")); - delim = ", "; - } - if (key_check_cap (key, KEY_CAP_CAN_SIGN)) - { - fprintf (fp, "%s%s", delim, _("signing")); - delim = ", "; - } - if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) - { - fprintf (fp, "%s%s", delim, _("certification")); - delim = ", "; - } + if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) { + fprintf (fp, "%s%s", delim, _("encryption")); + delim = ", "; + } + if (key_check_cap (key, KEY_CAP_CAN_SIGN)) { + fprintf (fp, "%s%s", delim, _("signing")); + delim = ", "; + } + if (key_check_cap (key, KEY_CAP_CAN_CERTIFY)) { + fprintf (fp, "%s%s", delim, _("certification")); + delim = ", "; + } putc ('\n', fp); - if (key->subkeys) - { - s = key->subkeys->fpr; - fputs (_("Fingerprint: "), fp); - if (is_pgp && strlen (s) == 40) - { - for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) - { - putc (*s, fp); - putc (s[1], fp); - putc (s[2], fp); - putc (s[3], fp); - putc (is_pgp? ' ':':', fp); - if (is_pgp && i == 4) - putc (' ', fp); - } - } - else - { - for (i=0; *s && s[1] && s[2]; s += 2, i++) - { - putc (*s, fp); - putc (s[1], fp); - putc (is_pgp? ' ':':', fp); - if (is_pgp && i == 7) - putc (' ', fp); - } - } - fprintf (fp, "%s\n", s); + if (key->subkeys) { + s = key->subkeys->fpr; + fputs (_("Fingerprint: "), fp); + if (is_pgp && mutt_strlen (s) == 40) { + for (i = 0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) { + putc (*s, fp); + putc (s[1], fp); + putc (s[2], fp); + putc (s[3], fp); + putc (is_pgp ? ' ' : ':', fp); + if (is_pgp && i == 4) + putc (' ', fp); + } } - - if (key->issuer_serial) - { - s = key->issuer_serial; - if (s) - fprintf (fp, "Serial-No .: 0x%s\n", s); + else { + for (i = 0; *s && s[1] && s[2]; s += 2, i++) { + putc (*s, fp); + putc (s[1], fp); + putc (is_pgp ? ' ' : ':', fp); + if (is_pgp && i == 7) + putc (' ', fp); + } } + fprintf (fp, "%s\n", s); + } - if (key->issuer_name) - { - s = key->issuer_name; - if (s) - { - fprintf (fp, "Issued By .: "); - parse_and_print_user_id (fp, s); - putc ('\n', fp); - } + if (key->issuer_serial) { + s = key->issuer_serial; + if (s) + fprintf (fp, "Serial-No .: 0x%s\n", s); + } + + if (key->issuer_name) { + s = key->issuer_name; + if (s) { + fprintf (fp, "Issued By .: "); + parse_and_print_user_id (fp, s); + putc ('\n', fp); } + } /* For PGP we list all subkeys. */ - if (is_pgp) - { - gpgme_subkey_t subkey = NULL; - - for (idx = 1, subkey = key->subkeys; subkey; - idx++, subkey = subkey->next) - { - s = subkey->keyid; - - putc ('\n', fp); - if ( strlen (s) == 16) - s += 8; /* display only the short keyID */ - fprintf (fp, "Subkey ....: 0x%s", s); - if (subkey->revoked) - { - putc (' ', fp); - fputs (_("[Revoked]"), fp); - } - if (subkey->invalid) - { - putc (' ', fp); - fputs (_("[Invalid]"), fp); - } - if (subkey->expired) - { - putc (' ', fp); - fputs (_("[Expired]"), fp); - } - if (subkey->disabled) - { - putc (' ', fp); - fputs (_("[Disabled]"), fp); - } - putc ('\n', fp); + if (is_pgp) { + gpgme_subkey_t subkey = NULL; + + for (idx = 1, subkey = key->subkeys; subkey; idx++, subkey = subkey->next) { + s = subkey->keyid; + + putc ('\n', fp); + if (mutt_strlen (s) == 16) + s += 8; /* display only the short keyID */ + fprintf (fp, "Subkey ....: 0x%s", s); + if (subkey->revoked) { + putc (' ', fp); + fputs (_("[Revoked]"), fp); + } + if (subkey->invalid) { + putc (' ', fp); + fputs (_("[Invalid]"), fp); + } + if (subkey->expired) { + putc (' ', fp); + fputs (_("[Expired]"), fp); + } + if (subkey->disabled) { + putc (' ', fp); + fputs (_("[Disabled]"), fp); + } + putc ('\n', fp); - if (subkey->timestamp > 0) - { - tt = subkey->timestamp; + if (subkey->timestamp > 0) { + tt = subkey->timestamp; - tm = localtime (&tt); + tm = localtime (&tt); #ifdef HAVE_LANGINFO_D_T_FMT - strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); + strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); #else - strftime (shortbuf, sizeof shortbuf, "%c", tm); + strftime (shortbuf, sizeof shortbuf, "%c", tm); #endif - fprintf (fp, "Valid From : %s\n", shortbuf); - } + fprintf (fp, "Valid From : %s\n", shortbuf); + } - if (subkey->expires > 0) - { - tt = subkey->expires; + if (subkey->expires > 0) { + tt = subkey->expires; - tm = localtime (&tt); + tm = localtime (&tt); #ifdef HAVE_LANGINFO_D_T_FMT - strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); + strftime (shortbuf, sizeof shortbuf, nl_langinfo (D_T_FMT), tm); #else - strftime (shortbuf, sizeof shortbuf, "%c", tm); + strftime (shortbuf, sizeof shortbuf, "%c", tm); #endif - fprintf (fp, "Valid To ..: %s\n", shortbuf); - } + fprintf (fp, "Valid To ..: %s\n", shortbuf); + } - if (subkey) - s = gpgme_pubkey_algo_name (subkey->pubkey_algo); - else - s = "?"; + if (subkey) + s = gpgme_pubkey_algo_name (subkey->pubkey_algo); + else + s = "?"; - if (subkey) - aval = subkey->length; - else - aval = 0; + if (subkey) + aval = subkey->length; + else + aval = 0; - fprintf (fp, "Key Type ..: %s, %lu bit %s\n", "PGP", aval, s); + fprintf (fp, "Key Type ..: %s, %lu bit %s\n", "PGP", aval, s); - fprintf (fp, "Key Usage .: "); - delim = ""; + fprintf (fp, "Key Usage .: "); + delim = ""; - if (subkey->can_encrypt) - { - fprintf (fp, "%s%s", delim, _("encryption")); - delim = ", "; - } - if (subkey->can_sign) - { - fprintf (fp, "%s%s", delim, _("signing")); - delim = ", "; - } - if (subkey->can_certify) - { - fprintf (fp, "%s%s", delim, _("certification")); - delim = ", "; - } - putc ('\n', fp); - } + if (subkey->can_encrypt) { + fprintf (fp, "%s%s", delim, _("encryption")); + delim = ", "; + } + if (subkey->can_sign) { + fprintf (fp, "%s%s", delim, _("signing")); + delim = ", "; + } + if (subkey->can_certify) { + fprintf (fp, "%s%s", delim, _("certification")); + delim = ", "; + } + putc ('\n', fp); } + } if (Locale) setlocale (LC_TIME, "C"); @@ -3172,8 +2949,7 @@ static void print_key_info (gpgme_key_t key, FILE *fp) /* Show detailed information about the selected key */ -static void -verify_key (crypt_key_t *key) +static void verify_key (crypt_key_t * key) { FILE *fp; char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX]; @@ -3184,59 +2960,53 @@ verify_key (crypt_key_t *key) int maxdepth = 100; mutt_mktemp (tempfile); - if (!(fp = safe_fopen (tempfile, "w"))) - { - mutt_perror _("Can't create temporary file"); - return; - } + if (!(fp = safe_fopen (tempfile, "w"))) { + mutt_perror (_("Can't create temporary file")); + + return; + } mutt_message _("Collecting data..."); print_key_info (key->kobj, fp); err = gpgme_new (&listctx); - if (err) - { - fprintf (fp, "Internal error: can't create gpgme context: %s\n", - gpgme_strerror (err)); - goto leave; - } + if (err) { + fprintf (fp, "Internal error: can't create gpgme context: %s\n", + gpgme_strerror (err)); + goto leave; + } if ((key->flags & KEYFLAG_ISX509)) - gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS); + gpgme_set_protocol (listctx, GPGME_PROTOCOL_CMS); k = key->kobj; gpgme_key_ref (k); - while ((s = k->chain_id) && k->subkeys && strcmp (s, k->subkeys->fpr) ) - { + while ((s = k->chain_id) && k->subkeys && mutt_strcmp (s, k->subkeys->fpr)) { + putc ('\n', fp); + err = gpgme_op_keylist_start (listctx, s, 0); + gpgme_key_release (k); + k = NULL; + if (!err) + err = gpgme_op_keylist_next (listctx, &k); + if (err) { + fprintf (fp, _("Error finding issuer key: %s\n"), gpgme_strerror (err)); + goto leave; + } + gpgme_op_keylist_end (listctx); + + print_key_info (k, fp); + if (!--maxdepth) { putc ('\n', fp); - err = gpgme_op_keylist_start (listctx, s, 0); - gpgme_key_release (k); - k = NULL; - if (!err) - err = gpgme_op_keylist_next (listctx, &k); - if (err) - { - fprintf (fp, _("Error finding issuer key: %s\n"), - gpgme_strerror (err)); - goto leave; - } - gpgme_op_keylist_end (listctx); - - print_key_info (k, fp); - if (!--maxdepth) - { - putc ('\n', fp); - fputs (_("Error: certification chain to long - stopping here\n"), - fp); - break; - } + fputs (_("Error: certification chain to long - stopping here\n"), fp); + break; } + } - leave: +leave: gpgme_key_release (k); gpgme_release (listctx); fclose (fp); mutt_clear_error (); - snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key)); + snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), crypt_keyid (key)); mutt_do_pager (cmd, tempfile, 0, NULL); } @@ -3248,7 +3018,7 @@ verify_key (crypt_key_t *key) /* Convert LIST into a pattern string suitable to be passed to GPGME. We need to convert spaces in an item into a '+' and '%' into "%25". */ -static char *list_to_pattern (LIST *list) +static char *list_to_pattern (LIST * list) { LIST *l; char *pattern, *p; @@ -3256,53 +3026,47 @@ static char *list_to_pattern (LIST *list) size_t n; n = 0; - for(l=list; l; l = l->next) - { - for(s = l->data; *s; s++) - { - if (*s == '%') - n += 2; - n++; - } - n++; /* delimiter or end of string */ + for (l = list; l; l = l->next) { + for (s = l->data; *s; s++) { + if (*s == '%') + n += 2; + n++; } - n++; /* make sure to allocate at least one byte */ - pattern = p = safe_calloc (1,n); - for(l=list; l; l = l->next) - { - s = l->data; - if (*s) - { - if (l != list) - *p++ = ' '; - for(s = l->data; *s; s++) - { - if (*s == '%') - { - *p++ = '%'; - *p++ = '2'; - *p++ = '5'; - } - else if (*s == '+') - { - *p++ = '%'; - *p++ = '2'; - *p++ = 'B'; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } + n++; /* delimiter or end of string */ + } + n++; /* make sure to allocate at least one byte */ + pattern = p = safe_calloc (1, n); + for (l = list; l; l = l->next) { + s = l->data; + if (*s) { + if (l != list) + *p++ = ' '; + for (s = l->data; *s; s++) { + if (*s == '%') { + *p++ = '%'; + *p++ = '2'; + *p++ = '5'; + } + else if (*s == '+') { + *p++ = '%'; + *p++ = '2'; + *p++ = 'B'; } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } } + } *p = 0; return pattern; } /* Return a list of keys which are candidates for the selection. Select by looking at the HINTS list. */ -static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret) +static crypt_key_t *get_candidates (LIST * hints, unsigned int app, + int secret) { crypt_key_t *db, *k, **kend; char *pattern; @@ -3315,143 +3079,128 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret) pattern = list_to_pattern (hints); if (!pattern) return NULL; - + err = gpgme_new (&ctx); - if (err) - { - mutt_error ("gpgme_new failed: %s", gpgme_strerror (err)); + if (err) { + mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err)); + FREE (&pattern); + return NULL; + } + + db = NULL; + kend = &db; + + if ((app & APPLICATION_PGP)) { + /* Its all a mess. That old GPGME expects different things + depending on the protocol. For gpg we don' t need percent + escaped pappert but simple strings passed in an array to the + keylist_ext_start function. */ + LIST *l; + size_t n; + char **patarr; + + for (l = hints, n = 0; l; l = l->next) { + if (l->data && *l->data) + n++; + } + if (!n) + goto no_pgphints; + + patarr = safe_calloc (n + 1, sizeof *patarr); + for (l = hints, n = 0; l; l = l->next) { + if (l->data && *l->data) + patarr[n++] = safe_strdup (l->data); + } + patarr[n] = NULL; + err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0); + for (n = 0; patarr[n]; n++) + FREE (&patarr[n]); + FREE (&patarr); + if (err) { + mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err)); + gpgme_release (ctx); FREE (&pattern); return NULL; } - db = NULL; - kend = &db; - - if ((app & APPLICATION_PGP)) - { - /* Its all a mess. That old GPGME expects different things - depending on the protocol. For gpg we don' t need percent - escaped pappert but simple strings passed in an array to the - keylist_ext_start function. */ - LIST *l; - size_t n; - char **patarr; - - for(l=hints, n=0; l; l = l->next) - { - if (l->data && *l->data) - n++; - } - if (!n) - goto no_pgphints; - - patarr = safe_calloc (n+1, sizeof *patarr); - for(l=hints, n=0; l; l = l->next) - { - if (l->data && *l->data) - patarr[n++] = safe_strdup (l->data); - } - patarr[n] = NULL; - err = gpgme_op_keylist_ext_start (ctx, (const char**)patarr, secret, 0); - for (n=0; patarr[n]; n++) - FREE (&patarr[n]); - FREE (&patarr); - if (err) - { - mutt_error ("gpgme_op_keylist_start failed: %s", - gpgme_strerror (err)); - gpgme_release (ctx); - FREE (&pattern); - return NULL; - } + while (!(err = gpgme_op_keylist_next (ctx, &key))) { + unsigned int flags = 0; - while (!(err = gpgme_op_keylist_next (ctx, &key)) ) - { - unsigned int 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 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 */ + if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) + flags |= KEYFLAG_CANENCRYPT; + if (key_check_cap (key, KEY_CAP_CAN_SIGN)) + flags |= KEYFLAG_CANSIGN; - for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) - { - k = safe_calloc (1, sizeof *k); - k->kobj = key; - k->idx = idx; - k->uid = uid->uid; - k->flags = flags; - *kend = k; - kend = &k->next; - } +#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; } - if (gpg_err_code (err) != GPG_ERR_EOF) - mutt_error ("gpgme_op_keylist_next failed: %s", gpgme_strerror (err)); - gpgme_op_keylist_end (ctx); - no_pgphints: - ; + } +#endif /* DISABLED code */ + + for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) { + k = safe_calloc (1, sizeof *k); + k->kobj = key; + k->idx = idx; + k->uid = uid->uid; + k->flags = flags; + *kend = k; + kend = &k->next; + } } + if (gpg_err_code (err) != GPG_ERR_EOF) + mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); + gpgme_op_keylist_end (ctx); + no_pgphints: + ; + } - if ((app & APPLICATION_SMIME)) - { - /* and now look for x509 certificates */ - gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); - err = gpgme_op_keylist_start (ctx, pattern, 0); - if (err) - { - mutt_error ("gpgme_op_keylist_start failed: %s", - gpgme_strerror (err)); - gpgme_release (ctx); - FREE (&pattern); - return NULL; - } + if ((app & APPLICATION_SMIME)) { + /* and now look for x509 certificates */ + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + err = gpgme_op_keylist_start (ctx, pattern, 0); + if (err) { + mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err)); + gpgme_release (ctx); + FREE (&pattern); + return NULL; + } - while (!(err = gpgme_op_keylist_next (ctx, &key)) ) - { - unsigned int flags = KEYFLAG_ISX509; - - if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) - flags |= KEYFLAG_CANENCRYPT; - if (key_check_cap (key, KEY_CAP_CAN_SIGN)) - flags |= KEYFLAG_CANSIGN; - - for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) - { - k = safe_calloc (1, sizeof *k); - k->kobj = key; - k->idx = idx; - k->uid = uid->uid; - k->flags = flags; - *kend = k; - kend = &k->next; - } - } - if (gpg_err_code (err) != GPG_ERR_EOF) - mutt_error ("gpgme_op_keylist_next failed: %s", gpgme_strerror (err)); - gpgme_op_keylist_end (ctx); + while (!(err = gpgme_op_keylist_next (ctx, &key))) { + unsigned int flags = KEYFLAG_ISX509; + + if (key_check_cap (key, KEY_CAP_CAN_ENCRYPT)) + flags |= KEYFLAG_CANENCRYPT; + if (key_check_cap (key, KEY_CAP_CAN_SIGN)) + flags |= KEYFLAG_CANSIGN; + + for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) { + k = safe_calloc (1, sizeof *k); + k->kobj = key; + k->idx = idx; + k->uid = uid->uid; + k->flags = flags; + *kend = k; + kend = &k->next; + } } + if (gpg_err_code (err) != GPG_ERR_EOF) + mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror (err)); + gpgme_op_keylist_end (ctx); + } gpgme_release (ctx); FREE (&pattern); @@ -3460,7 +3209,7 @@ static crypt_key_t *get_candidates (LIST * hints, unsigned int app, int secret) /* Add the string STR to the list HINTS. This list is later used to match addresses. */ -static LIST *crypt_add_string_to_hints (LIST *hints, const char *str) +static LIST *crypt_add_string_to_hints (LIST * hints, const char *str) { char *scratch; char *t; @@ -3469,12 +3218,11 @@ static LIST *crypt_add_string_to_hints (LIST *hints, const char *str) return hints; for (t = strtok (scratch, " ,.:\"()<>\n"); t; - t = strtok (NULL, " ,.:\"()<>\n")) - { - if (strlen (t) > 3) - hints = mutt_add_list (hints, t); - } - + t = strtok (NULL, " ,.:\"()<>\n")) { + if (mutt_strlen (t) > 3) + hints = mutt_add_list (hints, t); + } + FREE (&scratch); return hints; } @@ -3482,8 +3230,8 @@ static LIST *crypt_add_string_to_hints (LIST *hints, const char *str) /* Display a menu to select a key from the array KEYS. FORCED_VALID will be set to true on return if the user did override the the key's validity. */ -static crypt_key_t *crypt_select_key (crypt_key_t *keys, - ADDRESS * p, const char *s, +static crypt_key_t *crypt_select_key (crypt_key_t * keys, + ADDRESS * p, const char *s, unsigned int app, int *forced_valid) { int keymax; @@ -3501,47 +3249,43 @@ static crypt_key_t *crypt_select_key (crypt_key_t *keys, /* build the key table */ keymax = i = 0; key_table = NULL; - for (k = keys; k; k = k->next) - { - if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) - { - unusable = 1; - continue; - } - - if (i == keymax) - { - keymax += 20; - safe_realloc (&key_table, sizeof (crypt_key_t*)*keymax); - } - - key_table[i++] = k; + for (k = keys; k; k = k->next) { + if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) { + unusable = 1; + continue; } - if (!i && unusable) - { - mutt_error _("All matching keys are marked expired/revoked."); - mutt_sleep (1); - return NULL; + if (i == keymax) { + keymax += 20; + safe_realloc (&key_table, sizeof (crypt_key_t *) * keymax); } - switch (PgpSortKeys & SORT_MASK) - { - case SORT_DATE: - f = crypt_compare_date; - break; - case SORT_KEYID: - f = crypt_compare_keyid; - break; - case SORT_ADDRESS: - f = crypt_compare_address; - break; - case SORT_TRUST: - default: - f = crypt_compare_trust; - break; + key_table[i++] = k; + } + + if (!i && unusable) { + mutt_error _("All matching keys are marked expired/revoked."); + + mutt_sleep (1); + return NULL; } - qsort (key_table, i, sizeof (crypt_key_t*), f); + + switch (PgpSortKeys & SORT_MASK) { + case SORT_DATE: + f = crypt_compare_date; + break; + case SORT_KEYID: + f = crypt_compare_keyid; + break; + case SORT_ADDRESS: + f = crypt_compare_address; + break; + case SORT_TRUST: + default: + f = crypt_compare_trust; + break; + } + qsort (key_table, i, sizeof (crypt_key_t *), f); if (app & APPLICATION_PGP) menu_to_use = MENU_KEY_SELECT_PGP; @@ -3550,15 +3294,15 @@ static crypt_key_t *crypt_select_key (crypt_key_t *keys, helpstr[0] = 0; mutt_make_help (buf, sizeof (buf), _("Exit "), menu_to_use, OP_EXIT); - strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ + strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ mutt_make_help (buf, sizeof (buf), _("Select "), menu_to_use, - OP_GENERIC_SELECT_ENTRY); - strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ + OP_GENERIC_SELECT_ENTRY); + strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ mutt_make_help (buf, sizeof (buf), _("Check key "), menu_to_use, OP_VERIFY_KEY); - strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ + strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ mutt_make_help (buf, sizeof (buf), _("Help"), menu_to_use, OP_HELP); - strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ + strcat (helpstr, buf); /* __STRCAT_CHECKED__ */ menu = mutt_new_menu (); menu->max = i; @@ -3570,7 +3314,7 @@ static crypt_key_t *crypt_select_key (crypt_key_t *keys, { const char *ts; - if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME)) + if ((app & APPLICATION_PGP) && (app & APPLICATION_SMIME)) ts = _("PGP and S/MIME keys matching"); else if ((app & APPLICATION_PGP)) ts = _("PGP keys matching"); @@ -3583,120 +3327,110 @@ static crypt_key_t *crypt_select_key (crypt_key_t *keys, snprintf (buf, sizeof (buf), _("%s <%s>."), ts, p->mailbox); else snprintf (buf, sizeof (buf), _("%s \"%s\"."), ts, s); - menu->title = buf; + menu->title = buf; } mutt_clear_error (); k = NULL; - while (!done) - { - *forced_valid = 0; - switch (mutt_menuLoop (menu)) - { - case OP_VERIFY_KEY: - verify_key (key_table[menu->current]); - menu->redraw = REDRAW_FULL; - break; - - case OP_VIEW_ID: - mutt_message ("%s", key_table[menu->current]->uid); - break; - - case OP_GENERIC_SELECT_ENTRY: - /* FIXME make error reporting more verbose - this should be - easy because gpgme provides more information */ - if (option (OPTPGPCHECKTRUST)) - { - if (!crypt_key_is_valid (key_table[menu->current])) - { - mutt_error _("This key can't be used: " - "expired/disabled/revoked."); - break; - } - } - - if (option (OPTPGPCHECKTRUST) && - (!crypt_id_is_valid (key_table[menu->current]) - || !crypt_id_is_strong (key_table[menu->current]))) - { - const char *warn_s; - char buff[LONG_STRING]; - - if (key_table[menu->current]->flags & KEYFLAG_CANTUSE) - s = N_("ID is expired/disabled/revoked."); - else - { - gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN; - gpgme_user_id_t uid = NULL; - unsigned int j = 0; - - warn_s = "??"; - - uid = key_table[menu->current]->kobj->uids; - for (j = 0; (j < key_table[menu->current]->idx) && uid; - j++, uid = uid->next) - ; - if (uid) - val = uid->validity; - - switch (val) - { - case GPGME_VALIDITY_UNKNOWN: - case GPGME_VALIDITY_UNDEFINED: - warn_s = N_("ID has undefined validity."); - break; - case GPGME_VALIDITY_NEVER: - warn_s = N_("ID is not valid."); - break; - case GPGME_VALIDITY_MARGINAL: - warn_s = N_("ID is only marginally valid."); - break; - case GPGME_VALIDITY_FULL: - case GPGME_VALIDITY_ULTIMATE: - break; - } - - snprintf (buff, sizeof (buff), - _("%s Do you really want to use the key?"), - _(warn_s)); - - if (mutt_yesorno (buff, 0) != 1) - { - mutt_clear_error (); - break; - } - *forced_valid = 1; - } - } - - k = crypt_copy_key (key_table[menu->current]); - done = 1; - break; - - case OP_EXIT: - k = NULL; - done = 1; + while (!done) { + *forced_valid = 0; + switch (mutt_menuLoop (menu)) { + case OP_VERIFY_KEY: + verify_key (key_table[menu->current]); + menu->redraw = REDRAW_FULL; + break; + + case OP_VIEW_ID: + mutt_message ("%s", key_table[menu->current]->uid); + break; + + case OP_GENERIC_SELECT_ENTRY: + /* FIXME make error reporting more verbose - this should be + easy because gpgme provides more information */ + if (option (OPTPGPCHECKTRUST)) { + if (!crypt_key_is_valid (key_table[menu->current])) { + mutt_error _("This key can't be used: " + "expired/disabled/revoked."); break; } + } + + if (option (OPTPGPCHECKTRUST) && + (!crypt_id_is_valid (key_table[menu->current]) + || !crypt_id_is_strong (key_table[menu->current]))) { + const char *warn_s; + char buff[LONG_STRING]; + + if (key_table[menu->current]->flags & KEYFLAG_CANTUSE) + s = N_("ID is expired/disabled/revoked."); + else { + gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN; + gpgme_user_id_t uid = NULL; + unsigned int j = 0; + + warn_s = "??"; + + uid = key_table[menu->current]->kobj->uids; + for (j = 0; (j < key_table[menu->current]->idx) && uid; + j++, uid = uid->next); + if (uid) + val = uid->validity; + + switch (val) { + case GPGME_VALIDITY_UNKNOWN: + case GPGME_VALIDITY_UNDEFINED: + warn_s = N_("ID has undefined validity."); + break; + case GPGME_VALIDITY_NEVER: + warn_s = N_("ID is not valid."); + break; + case GPGME_VALIDITY_MARGINAL: + warn_s = N_("ID is only marginally valid."); + break; + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: + break; + } + + snprintf (buff, sizeof (buff), + _("%s Do you really want to use the key?"), _(warn_s)); + + if (mutt_yesorno (buff, 0) != 1) { + mutt_clear_error (); + break; + } + *forced_valid = 1; + } + } + + k = crypt_copy_key (key_table[menu->current]); + done = 1; + break; + + case OP_EXIT: + k = NULL; + done = 1; + break; } - + } + mutt_menuDestroy (&menu); FREE (&key_table); set_option (OPTNEEDREDRAW); - + return k; } static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, - unsigned int app, int *forced_valid) + unsigned int app, int *forced_valid) { ADDRESS *r, *p; LIST *hints = NULL; - int weak = 0; + int weak = 0; int invalid = 0; - int multi = 0; + int multi = 0; int this_key_has_strong; int this_key_has_weak; int this_key_has_invalid; @@ -3706,7 +3440,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, crypt_key_t *the_valid_key = NULL; crypt_key_t *matches = NULL; crypt_key_t **matches_endp = &matches; - + *forced_valid = 0; if (a && a->mailbox) @@ -3715,110 +3449,99 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities, hints = crypt_add_string_to_hints (hints, a->personal); mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox); - keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) ); + keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN)); mutt_free_list (&hints); - + if (!keys) return NULL; - - dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.", - a->personal, a->mailbox)); - for (k = keys; k; k = k->next) - { - dprint (5, (debugfile, " looking at key: %s `%.15s'\n", - crypt_keyid (k), k->uid)); - - if (abilities && !(k->flags & abilities)) - { - dprint (5, (debugfile, " insufficient abilities: Has %x, want %x\n", - k->flags, abilities)); - continue; - } + debug_print (5, ("looking for %s <%s>.\n", a->personal, a->mailbox)); - this_key_has_weak = 0; /* weak but valid match */ - this_key_has_invalid = 0; /* invalid match */ - this_key_has_strong = 0; /* strong and valid match */ - match = 0; /* any match */ - - r = rfc822_parse_adrlist (NULL, k->uid); - for (p = r; p; p = p->next) - { - int validity = crypt_id_matches_addr (a, p, k); - - if (validity & CRYPT_KV_MATCH) /* something matches */ - match = 1; - - /* is this key a strong candidate? */ - if ((validity & CRYPT_KV_VALID) - && (validity & CRYPT_KV_STRONGID) - && (validity & CRYPT_KV_ADDR)) - { - if (the_valid_key && the_valid_key != k) - multi = 1; - the_valid_key = k; - this_key_has_strong = 1; - } - else if ((validity & CRYPT_KV_MATCH) - && !(validity & CRYPT_KV_VALID)) - this_key_has_invalid = 1; - else if ((validity & CRYPT_KV_MATCH) - && (!(validity & CRYPT_KV_STRONGID) - || !(validity & CRYPT_KV_ADDR))) - this_key_has_weak = 1; - } - rfc822_free_address (&r); - - if (match) - { - crypt_key_t *tmp; - - if (!this_key_has_strong && this_key_has_invalid) - invalid = 1; - if (!this_key_has_strong && this_key_has_weak) - weak = 1; - - *matches_endp = tmp = crypt_copy_key (k); - matches_endp = &tmp->next; - the_valid_key = tmp; - } + for (k = keys; k; k = k->next) { + debug_print (5, (" looking at key: %s `%.15s'\n", crypt_keyid (k), k->uid)); + + if (abilities && !(k->flags & abilities)) { + debug_print (5, (" insufficient abilities: Has %x, want %x\n", k->flags, abilities)); + continue; } - + + this_key_has_weak = 0; /* weak but valid match */ + this_key_has_invalid = 0; /* invalid match */ + this_key_has_strong = 0; /* strong and valid match */ + match = 0; /* any match */ + + r = rfc822_parse_adrlist (NULL, k->uid); + for (p = r; p; p = p->next) { + int validity = crypt_id_matches_addr (a, p, k); + + if (validity & CRYPT_KV_MATCH) /* something matches */ + match = 1; + + /* is this key a strong candidate? */ + if ((validity & CRYPT_KV_VALID) + && (validity & CRYPT_KV_STRONGID) + && (validity & CRYPT_KV_ADDR)) { + if (the_valid_key && the_valid_key != k) + multi = 1; + the_valid_key = k; + this_key_has_strong = 1; + } + else if ((validity & CRYPT_KV_MATCH) + && !(validity & CRYPT_KV_VALID)) + this_key_has_invalid = 1; + else if ((validity & CRYPT_KV_MATCH) + && (!(validity & CRYPT_KV_STRONGID) + || !(validity & CRYPT_KV_ADDR))) + this_key_has_weak = 1; + } + rfc822_free_address (&r); + + if (match) { + crypt_key_t *tmp; + + if (!this_key_has_strong && this_key_has_invalid) + invalid = 1; + if (!this_key_has_strong && this_key_has_weak) + weak = 1; + + *matches_endp = tmp = crypt_copy_key (k); + matches_endp = &tmp->next; + the_valid_key = tmp; + } + } + crypt_free_key (&keys); - - 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); - } - crypt_free_key (&matches); + + 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 { + /* + * Else: Ask the user. + */ + k = crypt_select_key (matches, a, NULL, app, forced_valid); + } + crypt_free_key (&matches); + } + else k = NULL; - + return k; } static crypt_key_t *crypt_getkeybystr (char *p, short abilities, - unsigned int app, int *forced_valid) + unsigned int app, int *forced_valid) { LIST *hints = NULL; crypt_key_t *keys; @@ -3837,43 +3560,38 @@ static crypt_key_t *crypt_getkeybystr (char *p, short abilities, if (!keys) return NULL; - - for (k = keys; k; k = k->next) - { - if (abilities && !(k->flags & abilities)) - continue; - match = 0; - dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against " - "key %s, \"%s\": ", p, crypt_keyid (k), k->uid)); - - if (!*p - || !mutt_strcasecmp (p, crypt_keyid (k)) - || (!mutt_strncasecmp (p, "0x", 2) - && !mutt_strcasecmp (p + 2, crypt_keyid (k))) - || (option (OPTPGPLONGIDS) - && !mutt_strncasecmp (p, "0x", 2) - && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8)) - || mutt_stristr (k->uid, p)) - { - crypt_key_t *tmp; - - dprint (5, (debugfile, "match.\n")); - - *matches_endp = tmp = crypt_copy_key (k); - matches_endp = &tmp->next; - } + for (k = keys; k; k = k->next) { + if (abilities && !(k->flags & abilities)) + continue; + + match = 0; + debug_print (5, ("matching \"%s\" against " "key %s, \"%s\":\n", p, crypt_keyid (k), k->uid)); + + if (!*p || !safe_strcasecmp (p, crypt_keyid (k)) + || (!safe_strncasecmp (p, "0x", 2) + && !safe_strcasecmp (p + 2, crypt_keyid (k))) + || (option (OPTPGPLONGIDS) + && !safe_strncasecmp (p, "0x", 2) + && !safe_strcasecmp (p + 2, crypt_keyid (k) + 8)) + || str_isstr (k->uid, p)) { + crypt_key_t *tmp; + + debug_print (5, ("match.\n")); + + *matches_endp = tmp = crypt_copy_key (k); + matches_endp = &tmp->next; } - + } + crypt_free_key (&keys); - - if (matches) - { - k = crypt_select_key (matches, NULL, p, app, forced_valid); - crypt_free_key (&matches); - return k; - } - + + if (matches) { + k = crypt_select_key (matches, NULL, p, app, forced_valid); + crypt_free_key (&matches); + return k; + } + return NULL; } @@ -3882,11 +3600,10 @@ static crypt_key_t *crypt_getkeybystr (char *p, short abilities, default. ABILITIES describe the required key abilities (sign, encrypt) and APP the type of the requested key; ether S/MIME or PGP. Return a copy of the key or NULL if not found. */ -static crypt_key_t *crypt_ask_for_key (char *tag, - char *whatfor, +static crypt_key_t *crypt_ask_for_key (char *tag, + char *whatfor, short abilities, - unsigned int app, - int *forced_valid) + unsigned int app, int *forced_valid) { crypt_key_t *key; char resp[SHORT_STRING]; @@ -3900,49 +3617,44 @@ static crypt_key_t *crypt_ask_for_key (char *tag, *forced_valid = 0; resp[0] = 0; - if (whatfor) - { - - for (l = id_defaults; l; l = l->next) - if (!mutt_strcasecmp (whatfor, l->what)) - { - strfcpy (resp, NONULL (l->dflt), sizeof (resp)); - break; - } - } + if (whatfor) { + for (l = id_defaults; l; l = l->next) + if (!safe_strcasecmp (whatfor, l->what)) { + strfcpy (resp, NONULL (l->dflt), sizeof (resp)); + break; + } + } - for (;;) - { - resp[0] = 0; - if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0) - return NULL; - - if (whatfor) - { - if (l) - mutt_str_replace (&l->dflt, resp); - else - { - l = safe_malloc (sizeof (struct crypt_cache)); - l->next = id_defaults; - id_defaults = l; - l->what = safe_strdup (whatfor); - l->dflt = safe_strdup (resp); - } - } - - if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid))) - return key; - - BEEP (); + + for (;;) { + resp[0] = 0; + if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0) + return NULL; + + if (whatfor) { + if (l) + str_replace (&l->dflt, resp); + else { + l = safe_malloc (sizeof (struct crypt_cache)); + l->next = id_defaults; + id_defaults = l; + l->what = safe_strdup (whatfor); + l->dflt = safe_strdup (resp); + } } + + if ((key = crypt_getkeybystr (resp, abilities, app, forced_valid))) + return key; + + BEEP (); + } /* not reached */ } /* This routine attempts to find the keyids of the recipients of a message. It returns NULL if any of the keys can not be found. */ -static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, +static char *find_keys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc, unsigned int app) { char *keyID, *keylist = NULL, *t; @@ -3956,127 +3668,123 @@ static char *find_keys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, const char *fqdn = mutt_fqdn (1); #if 0 - *r_application = APPLICATION_PGP|APPLICATION_SMIME; + *r_application = APPLICATION_PGP | APPLICATION_SMIME; #endif - - for (i = 0; i < 3; i++) - { - switch (i) - { - case 0: p = to; break; - case 1: p = cc; break; - case 2: p = bcc; break; - default: abort (); - } - - *last = rfc822_cpy_adr (p); - while (*last) - last = &((*last)->next); + + for (i = 0; i < 3; i++) { + switch (i) { + case 0: + p = to; + break; + case 1: + p = cc; + break; + case 2: + p = bcc; + break; + default: + abort (); } - + + *last = rfc822_cpy_adr (p); + while (*last) + last = &((*last)->next); + } + if (fqdn) rfc822_qualify (tmp, fqdn); - + tmp = mutt_remove_duplicates (tmp); - - for (p = tmp; p ; p = p->next) - { - char buf[LONG_STRING]; - int forced_valid = 0; - - q = p; - k_info = NULL; - - if ((keyID = mutt_crypt_hook (p)) != NULL) - { - int r; - snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), - keyID, p->mailbox); - if ((r = mutt_yesorno (buf, M_YES)) == M_YES) - { - /* check for e-mail address */ - if ((t = strchr (keyID, '@')) && - (addr = rfc822_parse_adrlist (NULL, keyID))) - { - if (fqdn) - rfc822_qualify (addr, fqdn); - q = addr; - } - else - { -#if 0 - k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, - *r_application, &forced_valid); + + for (p = tmp; p; p = p->next) { + char buf[LONG_STRING]; + int forced_valid = 0; + + q = p; + k_info = NULL; + + if ((keyID = mutt_crypt_hook (p)) != NULL) { + int r; + + snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), + keyID, p->mailbox); + if ((r = mutt_yesorno (buf, M_YES)) == M_YES) { + /* check for e-mail address */ + if ((t = strchr (keyID, '@')) && + (addr = rfc822_parse_adrlist (NULL, keyID))) { + if (fqdn) + rfc822_qualify (addr, fqdn); + q = addr; + } + else { +#if 0 + k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, + *r_application, &forced_valid); #else - k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, - app, &forced_valid); + k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, + app, &forced_valid); #endif - } - } - else if (r == -1) - { - FREE (&keylist); - rfc822_free_address (&tmp); - rfc822_free_address (&addr); - return NULL; - } } + } + else if (r == -1) { + FREE (&keylist); + rfc822_free_address (&tmp); + rfc822_free_address (&addr); + return NULL; + } + } - if (k_info == NULL - && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT, - app, &forced_valid)) == NULL) - { - snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); - - if ((key = crypt_ask_for_key (buf, q->mailbox, - KEYFLAG_CANENCRYPT, + if (k_info == NULL + && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT, + app, &forced_valid)) == NULL) { + snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox); + + if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT, #if 0 - *r_application, + *r_application, #else - app, + app, #endif - &forced_valid)) == NULL) - { - FREE (&keylist); - rfc822_free_address (&tmp); - rfc822_free_address (&addr); - return NULL; - } - } - else - key = k_info; + &forced_valid)) == NULL) { + FREE (&keylist); + rfc822_free_address (&tmp); + rfc822_free_address (&addr); + return NULL; + } + } + else + key = k_info; - { - const char *s = crypt_fpr (key); + { + const char *s = crypt_fpr (key); #if 0 - if (key->flags & KEYFLAG_ISX509) - *r_application &= ~APPLICATION_PGP; - if (!(key->flags & KEYFLAG_ISX509)) - *r_application &= ~APPLICATION_SMIME; + if (key->flags & KEYFLAG_ISX509) + *r_application &= ~APPLICATION_PGP; + if (!(key->flags & KEYFLAG_ISX509)) + *r_application &= ~APPLICATION_SMIME; #endif - - keylist_size += mutt_strlen (s) + 4 + 1; - safe_realloc (&keylist, keylist_size); - sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */ - keylist_used ? " " : "", s, - forced_valid? "!":""); - } - keylist_used = mutt_strlen (keylist); - - crypt_free_key (&key); - rfc822_free_address (&addr); + + keylist_size += mutt_strlen (s) + 4 + 1; + safe_realloc (&keylist, keylist_size); + sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */ + keylist_used ? " " : "", s, forced_valid ? "!" : ""); } + keylist_used = mutt_strlen (keylist); + + crypt_free_key (&key); + rfc822_free_address (&addr); + } rfc822_free_address (&tmp); return (keylist); } -char *pgp_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +char *pgp_gpgme_findkeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc) { return find_keys (to, cc, bcc, APPLICATION_PGP); } -char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) +char *smime_gpgme_findkeys (ADDRESS * to, ADDRESS * cc, ADDRESS * bcc) { return find_keys (to, cc, bcc, APPLICATION_SMIME); } @@ -4089,12 +3797,11 @@ char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) 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); - } + 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) @@ -4106,7 +3813,7 @@ void smime_gpgme_init (void) { } -static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime) +static int gpgme_send_menu (HEADER * msg, int *redraw, int is_smime) { crypt_key_t *p; char input_signas[SHORT_STRING]; @@ -4118,135 +3825,130 @@ static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime) is_smime = 1; if (is_smime) - choice = mutt_multi_choice ( - _("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (t)oggle or (f)orget it?"), - _("esabtf")); - else - choice = mutt_multi_choice ( - _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (t)oggle or (f)orget it?"), - _("esabtf")); - - switch (choice) - { - case 1: /* (e)ncrypt */ + choice = + mutt_multi_choice (_ + ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"), + _("esabpfc")); + else + choice = + mutt_multi_choice (_ + ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"), + _("esabmfc")); + + switch (choice) { + case 1: /* (e)ncrypt */ msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT); + msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN); break; - case 2: /* (s)ign */ - msg->security |= (is_smime? SMIMESIGN :PGPSIGN); + case 2: /* (s)ign */ + msg->security |= (is_smime ? SMIMESIGN : PGPSIGN); + msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT); break; - case 3: /* sign (a)s */ + 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))) - { + is_smime ? APPLICATION_SMIME : + APPLICATION_PGP, NULL))) { snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p)); - mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas); - crypt_free_key (&p); - - msg->security |= (is_smime? SMIMESIGN:PGPSIGN); + str_replace (is_smime ? &SmimeDefaultKey : &PgpSignAs, + input_signas); + crypt_free_key (&p); + + msg->security |= (is_smime ? SMIMESIGN : PGPSIGN); } - else - { - msg->security &= (is_smime? ~SMIMESIGN : ~PGPSIGN); +#if 0 + else { + msg->security &= (is_smime ? ~SMIMESIGN : ~PGPSIGN); } +#endif *redraw = REDRAW_FULL; break; - case 4: /* (b)oth */ - msg->security = (is_smime? (SMIMEENCRYPT|SMIMESIGN):(PGPENCRYPT|PGPSIGN)); + case 4: /* (b)oth */ + msg->security = + (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN)); break; - case 5: /* (t)oggle */ + case 5: /* (p)gp or s/(m)ime */ is_smime = !is_smime; break; - case 6: /* (f)orget it */ + case 6: /* (c)lear */ msg->security = 0; break; } - if (choice == 6) - ; - else if (is_smime) - { - msg->security &= ~APPLICATION_PGP; - msg->security |= APPLICATION_SMIME; - } - else - { - msg->security &= ~APPLICATION_SMIME; - msg->security |= APPLICATION_PGP; - } - + if (choice == 6 || choice == 7); + else if (is_smime) { + msg->security &= ~APPLICATION_PGP; + msg->security |= APPLICATION_SMIME; + } + else { + msg->security &= ~APPLICATION_SMIME; + msg->security |= APPLICATION_PGP; + } + return (msg->security); } -int pgp_gpgme_send_menu (HEADER *msg, int *redraw) +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) +int smime_gpgme_send_menu (HEADER * msg, int *redraw) { return gpgme_send_menu (msg, redraw, 1); } -static int verify_sender (HEADER *h, gpgme_protocol_t protocol) +static int verify_sender (HEADER * h, gpgme_protocol_t protocol) { ADDRESS *sender = NULL; unsigned int ret = 1; - if (h->env->from) - { - h->env->from = mutt_expand_aliases (h->env->from); - sender = h->env->from; - } - else if (h->env->sender) - { - h->env->sender = mutt_expand_aliases (h->env->sender); - sender = h->env->sender; - } + if (h->env->from) { + h->env->from = mutt_expand_aliases (h->env->from); + sender = h->env->from; + } + else if (h->env->sender) { + h->env->sender = mutt_expand_aliases (h->env->sender); + sender = h->env->sender; + } - if (sender) - { - if (signature_key) - { - gpgme_key_t key = signature_key; - gpgme_user_id_t uid = NULL; - int sender_length = 0; - int uid_length = 0; - - sender_length = strlen (sender->mailbox); - for (uid = key->uids; uid && ret; uid = uid->next) - { - uid_length = strlen (uid->email); - if (1 - && (uid->email[0] == '<') - && (uid->email[uid_length - 1] == '>') - && (uid_length == sender_length + 2) - && (! strncmp (uid->email + 1, sender->mailbox, sender_length))) - ret = 0; - } - } - else - mutt_any_key_to_continue ("Failed to verify sender"); + if (sender) { + if (signature_key) { + gpgme_key_t key = signature_key; + gpgme_user_id_t uid = NULL; + int sender_length = 0; + int uid_length = 0; + + sender_length = mutt_strlen (sender->mailbox); + for (uid = key->uids; uid && ret; uid = uid->next) { + uid_length = mutt_strlen (uid->email); + if (1 && (uid->email[0] == '<') + && (uid->email[uid_length - 1] == '>') + && (uid_length == sender_length + 2) + && (!strncmp (uid->email + 1, sender->mailbox, sender_length))) + ret = 0; + } } + else + mutt_any_key_to_continue ("Failed to verify sender"); + } else mutt_any_key_to_continue ("Failed to figure out sender"); - if (signature_key) - { - gpgme_key_release (signature_key); - signature_key = NULL; - } + if (signature_key) { + gpgme_key_release (signature_key); + signature_key = NULL; + } return ret; } -int smime_gpgme_verify_sender (HEADER *h) +int smime_gpgme_verify_sender (HEADER * h) { return verify_sender (h, GPGME_PROTOCOL_CMS); }