#define CRYPT_KV_STRONGID 8
#define CRYPT_KV_MATCH (CRYPT_KV_ADDR|CRYPT_KV_STRING)
-/*
- * Type definitions.
- */
-
-struct crypt_cache {
- char *what;
- char *dflt;
- struct crypt_cache *next;
-};
-
struct dn_array_s {
- char *key;
- char *value;
+ 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 {
- 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) */
-} crypt_key_t;
+typedef struct cryptkey_t {
+ struct cryptkey_t *next;
+ int idx; /* and the user ID at this index */
+ int flags; /* global and per uid flags (for convenience) */
+ gpgme_key_t kobj;
+ const char *uid; /* and for convenience point to this user ID */
+} cryptkey_t;
+
+DO_INIT(cryptkey_t, cryptkey);
+static void cryptkey_wipe(cryptkey_t *key) {
+ gpgme_key_release(key->kobj);
+}
+DO_NEW(cryptkey_t, cryptkey);
+DO_DELETE(cryptkey_t, cryptkey);
+DO_SLIST(cryptkey_t, key, cryptkey_delete);
+
+static cryptkey_t *cryptkey_dup(const cryptkey_t *k)
+{
+ cryptkey_t *res = cryptkey_new();
+ *res = *k;
+ res->next = NULL;
+ gpgme_key_ref(k->kobj);
+ return res;
+}
typedef struct crypt_entry {
- ssize_t num;
- crypt_key_t *key;
+ ssize_t num;
+ cryptkey_t *key;
} crypt_entry_t;
-
-static struct crypt_cache *id_defaults = NULL;
static gpgme_key_t signature_key = NULL;
-/*
- * General helper functions.
- */
-
static void convert_to_7bit (BODY * a)
{
- while (a) {
- if (a->type == TYPEMULTIPART) {
- if (a->encoding != ENC7BIT) {
- a->encoding = ENC7BIT;
- convert_to_7bit (a->parts);
- } else {
- convert_to_7bit (a->parts);
- }
- }
- else if (a->type == TYPEMESSAGE &&
- m_strcasecmp(a->subtype, "delivery-status")) {
- if (a->encoding != ENC7BIT)
- mutt_message_to_7bit (a, NULL);
+ for (; a; a = a->next) {
+ int tok = mime_which_token(a->subtype, -1);
+
+ if (a->type == TYPEMULTIPART) {
+ a->encoding = ENC7BIT;
+ convert_to_7bit(a->parts);
+ } else if (a->type == TYPEMESSAGE && tok == MIME_DELIVERY_STATUS) {
+ if (a->encoding != ENC7BIT)
+ mutt_message_to_7bit(a, NULL);
+ } else if (a->encoding == ENC8BIT) {
+ a->encoding = ENCQUOTEDPRINTABLE;
+ } else if (a->encoding == ENCBINARY) {
+ a->encoding = ENCBASE64;
+ } else if (a->content && a->encoding != ENCBASE64
+ && (a->content->from || a->content->space))
+ {
+ a->encoding = ENCQUOTEDPRINTABLE;
+ }
}
- else if (a->encoding == ENC8BIT)
- a->encoding = ENCQUOTEDPRINTABLE;
- else if (a->encoding == ENCBINARY)
- a->encoding = ENCBASE64;
- else if (a->content && a->encoding != ENCBASE64 &&
- (a->content->from || a->content->space))
- a->encoding = ENCQUOTEDPRINTABLE;
- a = a->next;
- }
}
/* 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, ssize_t len)
{
- char *tstr;
+ char *tstr;
- tstr = p_dupstr(buf, len);
- mutt_convert_string (&tstr, "utf-8", MCharset.charset, M_ICONV_HOOK_FROM);
- fputs (tstr, fp);
- p_delete(&tstr);
+ tstr = p_dupstr(buf, len);
+ mutt_convert_string(&tstr, "utf-8", MCharset.charset, M_ICONV_HOOK_FROM);
+ fputs(tstr, fp);
+ p_delete(&tstr);
}
-
-/*
- * Key management.
- */
-
/* 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 (cryptkey_t * k)
{
- const char *s = "????????";
-
- if (k->kobj && k->kobj->subkeys) {
- s = k->kobj->subkeys->keyid;
- if ((!option (OPTPGPLONGIDS)) && (m_strlen(s) == 16))
- /* Return only the short keyID. */
- s += 8;
- }
+ if (k->kobj && k->kobj->subkeys) {
+ const char *s = k->kobj->subkeys->keyid;
+ return m_strlen(s) == 16 ? s + 8 : s;
+ }
- return s;
+ return "????????";
}
/* Return the hexstring fingerprint from the key K. */
-static const char *crypt_fpr (crypt_key_t * k)
+static const char *crypt_fpr (cryptkey_t * k)
{
- const char *s = "";
-
- if (k->kobj && k->kobj->subkeys)
- s = k->kobj->subkeys->fpr;
-
- return s;
+ return k->kobj && k->kobj->subkeys ? k->kobj->subkeys->fpr : "";
}
/* Parse FLAGS and return a statically allocated(!) string with them. */
return ' ';
}
-/* Return a copy of KEY. */
-static crypt_key_t *crypt_copy_key (crypt_key_t *key)
-{
- crypt_key_t *k;
-
- k = p_new(crypt_key_t, 1);
- k->kobj = key->kobj;
- gpgme_key_ref (key->kobj);
- k->idx = key->idx;
- k->uid = key->uid;
- k->flags = key->flags;
-
- return k;
-}
-
-/* Release all the keys at the address of KEYLIST and set the address
- to NULL. */
-static void crypt_free_key (crypt_key_t ** keylist)
-{
- while (*keylist) {
- crypt_key_t *k = (*keylist)->next;
-
- p_delete(&k);
- *keylist = k;
- }
-}
-
-/* Return trute when key K is valid. */
-static int crypt_key_is_valid (crypt_key_t * k)
-{
- if (k->flags & KEYFLAG_CANTUSE)
- return 0;
- return 1;
-}
-
/* Return true whe validity of KEY is sufficient. */
-static int crypt_id_is_strong (crypt_key_t * key)
+static int crypt_id_is_strong (cryptkey_t * key)
{
- gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
- gpgme_user_id_t uid = NULL;
- int is_strong = 0;
- int i = 0;
-
- if ((key->flags & KEYFLAG_ISX509))
- return 1;
-
- for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
- 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;
+ gpgme_user_id_t uid;
+ int i;
- case GPGME_VALIDITY_FULL:
- case GPGME_VALIDITY_ULTIMATE:
- is_strong = 1;
- break;
- }
+ if (key->flags & KEYFLAG_ISX509)
+ return 1;
- return is_strong;
-}
+ for (i = 0, uid = key->kobj->uids; uid; i++, uid = uid->next) {
+ if (i == key->idx) {
+ return uid->validity == GPGME_VALIDITY_FULL
+ || uid->validity == GPGME_VALIDITY_ULTIMATE;
+ }
+ }
-/* Return true when the KEY is valid, i.e. not marked as unusable. */
-static int crypt_id_is_valid (crypt_key_t * key)
-{
- return !(key->flags & KEYFLAG_CANTUSE);
+ return 0;
}
/* 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_t * addr, address_t * u_addr,
- crypt_key_t * key)
+static int
+crypt_id_matches_addr(address_t *addr, address_t *u_addr, cryptkey_t *key)
{
- int rv = 0;
+ int rv = 0;
- if (crypt_id_is_valid (key))
- rv |= CRYPT_KV_VALID;
+ if (!(key->flags & KEYFLAG_CANTUSE))
+ rv |= CRYPT_KV_VALID;
- if (crypt_id_is_strong (key))
- rv |= CRYPT_KV_STRONGID;
+ if (crypt_id_is_strong(key))
+ rv |= CRYPT_KV_STRONGID;
- if (addr->mailbox && u_addr->mailbox
- && m_strcasecmp(addr->mailbox, u_addr->mailbox) == 0)
- rv |= CRYPT_KV_ADDR;
+ if (addr->mailbox && !m_strcasecmp(addr->mailbox, u_addr->mailbox))
+ rv |= CRYPT_KV_ADDR;
- if (addr->personal && u_addr->personal
- && m_strcasecmp(addr->personal, u_addr->personal) == 0)
- rv |= CRYPT_KV_STRING;
+ if (addr->personal && m_strcasecmp(addr->personal, u_addr->personal))
+ rv |= CRYPT_KV_STRING;
- return rv;
+ return rv;
}
-/*
- * GPGME convenient functions.
- */
-
/* Create a new gpgme context and return it. With FOR_SMIME set to
true, the protocol of the context is set to CMS. */
-static gpgme_ctx_t create_gpgme_context (int for_smime)
+static gpgme_ctx_t create_gpgme_context(int for_smime)
{
- gpgme_error_t err;
- gpgme_ctx_t ctx;
-
- err = gpgme_new (&ctx);
- if (err) {
- mutt_error (_("error creating gpgme context: %s\n"), gpgme_strerror (err));
- sleep (2);
- mutt_exit (1);
- }
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
- if (for_smime) {
- err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
+ err = gpgme_new (&ctx);
if (err) {
- mutt_error (_("error enabling CMS protocol: %s\n"), gpgme_strerror (err));
- sleep (2);
- mutt_exit (1);
+ mutt_error(_("error creating gpgme context: %s\n"),
+ gpgme_strerror(err));
+ sleep(2);
+ mutt_exit(1);
}
- }
+ if (!for_smime)
+ return ctx;
- return ctx;
+ 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;
}
/* Create a new gpgme data object. This is a wrapper to die on
error. */
-static gpgme_data_t create_gpgme_data (void)
+static gpgme_data_t create_gpgme_data(void)
{
- gpgme_error_t err;
- gpgme_data_t data;
+ gpgme_error_t err;
+ 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);
- }
- return 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);
+ }
+ 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;
+ gpgme_data_t data;
+ int err = 0;
+ FILE *fptmp = tmpfile();
- fptmp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
- if (!fptmp) {
- mutt_perror (_("Can't create temporary file"));
- return NULL;
- }
+ if (!fptmp) {
+ mutt_perror (_("Can't create temporary file"));
+ return NULL;
+ }
- mutt_write_mime_header (a, fptmp);
- fputc ('\n', fptmp);
- mutt_write_mime_body (a, fptmp);
+ mutt_write_mime_header(a, fptmp);
+ fputc('\n', fptmp);
+ mutt_write_mime_body(a, fptmp);
+ rewind(fptmp);
- if (convert) {
- int c, hadcr = 0;
- unsigned char buf[1];
+ if (convert) {
+ char buf[STRING];
+ int spare = 0;
- 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);
- }
+ data = create_gpgme_data();
+ while (fgets(buf + spare, sizeof(buf) - 1, fptmp)) {
+ int l = m_strlen(buf);
- hadcr = 0;
- }
- /* FIXME: This is quite suboptimal */
- buf[0] = c;
- gpgme_data_write (data, buf, 1);
+ spare = buf[l - 1] != '\n';
+ if (!spare) {
+ if (l > 2 && buf[l - 2] == '\r') {
+ buf[l - 2] = '\n';
+ l--;
+ }
+ }
+ gpgme_data_write(data, buf, l - spare);
+ if (spare)
+ buf[0] = buf[l - 1];
+ }
+ if (spare)
+ gpgme_data_write(data, buf, 1);
+ gpgme_data_seek(data, 0, SEEK_SET);
+ } else {
+ err = gpgme_data_new_from_stream(&data, fptmp);
+ }
+ m_fclose(&fptmp);
+ if (err) {
+ mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
+ return NULL;
}
- gpgme_data_seek (data, 0, SEEK_SET);
- } else {
- err = gpgme_data_new_from_file (&data, tempfile, 1);
- }
- m_fclose(&fptmp);
- unlink (tempfile);
- if (err) {
- mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err));
- return NULL;
- }
- return data;
+ return data;
}
/* 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;
+ 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;
- }
+ 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;
+ }
- return data;
+ 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;
- ssize_t nread;
-
- 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;
- }
+ int err;
+ char buf[4096], *p;
+ ssize_t nread;
- 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);
+ 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;
}
- 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 (ferror (fp)) {
+ mutt_perror ("[tempfile]");
+ return -1;
+ }
}
- }
- if (nread == -1) {
- mutt_error (_("error reading data object: %s\n"), strerror (errno));
- return -1;
- }
- return 0;
+ 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];
- FILE *fp;
- ssize_t nread = 0;
+ int err;
+ char tempfile[_POSIX_PATH_MAX];
+ FILE *fp;
+ ssize_t nread = 0;
- fp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
- if (!fp) {
- mutt_perror (_("Can't create temporary file"));
- return NULL;
- }
+ fp = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
+ if (!fp) {
+ mutt_perror (_("Can't create temporary file"));
+ return NULL;
+ }
- err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1)
- ? gpgme_error_from_errno (errno) : 0);
- if (!err) {
- char buf[4096];
+ 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 (_("Can't create temporary file"));
+ m_fclose(&fp);
+ unlink (tempfile);
+ return NULL;
+ }
+ }
+ }
- while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) {
- if (fwrite (buf, nread, 1, fp) != 1) {
- mutt_perror (_("Can't create temporary file"));
- m_fclose(&fp);
+ if (nread == -1) {
+ mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
unlink (tempfile);
+ m_fclose(&fp);
return NULL;
- }
}
- }
- if (ret_fp)
- rewind (fp);
- else
- m_fclose(&fp);
- if (nread == -1) {
- mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err));
- unlink (tempfile);
- m_fclose(&fp);
- return NULL;
- }
- if (ret_fp)
- *ret_fp = fp;
- return m_strdup(tempfile);
+ if (ret_fp) {
+ rewind(fp);
+ *ret_fp = fp;
+ } else {
+ m_fclose(&fp);
+ }
+ return m_strdup(tempfile);
}
/* Create a GpgmeRecipientSet from the keys in the string KEYLIST.
The keys must be space delimited. */
-static gpgme_key_t *create_recipient_set (const char *keylist,
- gpgme_protocol_t protocol)
+static gpgme_key_t *
+create_recipient_set(const char *keylist, gpgme_protocol_t protocol)
{
int err;
const char *s;
}
err = gpgme_op_keylist_next (listctx, &key2);
if (!err) {
- gpgme_key_release (key);
- gpgme_key_release (key2);
+ gpgme_key_unref(key);
+ gpgme_key_unref(key2);
gpgme_release (listctx);
mutt_error (_("ambiguous specification of secret key `%s'\n"), signid);
return -1;
gpgme_signers_clear (ctx);
err = gpgme_signers_add (ctx, key);
- gpgme_key_release (key);
+ gpgme_key_unref(key);
if (err) {
mutt_error (_("error setting secret key `%s': %s\n"),
signid, gpgme_strerror (err));
/* 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;
convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
- message = body_to_data_object (a, 1);
+ message = body_to_data_object(a, 1);
if (!message)
return NULL;
signature = create_gpgme_data ();
return a;
}
-/*
- * Implementation of `encrypt_message'.
- */
-
/* Encrypt the mail body A to all keys given as space separated keyids
or fingerprints in KEYLIST and return the encrypted body. */
static BODY *crypt_pgp_encrypt_message (BODY * a, char *keylist, int sign)
if (sign)
convert_to_7bit (a);
- plaintext = body_to_data_object (a, 0);
+ plaintext = body_to_data_object(a, 0);
if (!plaintext) {
p_delete(&rset);
return NULL;
t->parts->next->use_disp = 1;
t->parts->next->disposition = DISPINLINE;
t->parts->next->unlink = 1; /* delete after sending the message */
- t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime
- can save */
+ t->parts->next->d_filename = m_strdup("msg.asc");
return t;
}
-/*
- * Implementation of `smime_build_smime_entity'.
- */
-
/* Encrypt the mail body A to all keys given as space separated
fingerprints in KEYLIST and return the S/MIME encrypted body. */
static BODY *crypt_smime_build_smime_entity (BODY * a, char *keylist)
if (!rset)
return NULL;
- plaintext = body_to_data_object (a, 0);
+ plaintext = body_to_data_object(a, 0);
if (!plaintext) {
p_delete(&rset);
return NULL;
return t;
}
-
-/* Implementation of `verify_one'. */
-
/* Display the common attributes of the signature summary SUM.
Return 1 if there is is a severe warning.
*/
return -1; /* Signature not found. */
if (signature_key) {
- gpgme_key_release (signature_key);
+ gpgme_key_unref(signature_key);
signature_key = NULL;
}
}
if (key != signature_key)
- gpgme_key_release (key);
+ gpgme_key_unref(key);
}
return anybad ? 1 : anywarn ? 2 : 0;
int anybad = 0;
if (signature_key) {
- gpgme_key_release (signature_key);
+ gpgme_key_unref(signature_key);
signature_key = NULL;
}
return badsig ? 1 : anywarn ? 2 : 0;
}
-/*
- * Implementation of `decrypt_part'.
- */
-
/* Decrypt a PGP or SMIME message (depending on the boolean flag
IS_SMIME) with body A described further by state S. Write
plaintext out to file FPOUT and return a new body. For PGP returns
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,
- int *r_is_signed)
+static BODY *
+decrypt_part(BODY *a, STATE *s, FILE *fpout, int is_smime, int *r_is_signed)
{
struct stat info;
BODY *tattach;
/* 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 crypt_smime_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b,
- BODY ** cur)
+int crypt_smime_decrypt_mime(FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
{
char tempfile[_POSIX_PATH_MAX];
STATE s;
}
-/*
- * 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];
return 1;
}
-int crypt_pgp_check_traditional (FILE * fp, BODY * b, int tagged_only)
+int crypt_pgp_check_traditional(FILE *fp, BODY *b, int tagged_only)
{
int rv = 0;
int r;
return rv;
}
-
-/* Implementation of `application_handler'. */
-
/*
Copy a clearsigned message, and strip the signature and PGP's
dash-escaping.
(Note that we aren't worse than Outlook & Cie in this, and also
note that we can successfully handle anything produced by any
existing versions of mutt.) */
-
-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;
m_fclose(&fp);
}
-
/* Support for classic_application/pgp */
-int crypt_pgp_application_pgp_handler (BODY * m, STATE * s)
+int crypt_pgp_application_pgp_handler(BODY *m, STATE *s)
{
int needpass = -1, pgp_keyblock = 0;
int clearsign = 0;
return (err);
}
-/* Implementation of `encrypted_handler'. */
-
/* MIME handler for pgp/mime encrypted messages. */
int crypt_pgp_encrypted_handler (BODY * a, STATE * s)
{
{
char fmt[16];
crypt_entry_t *entry;
- crypt_key_t *key;
+ cryptkey_t *key;
int kflags = 0;
int optional = (flags & M_FORMAT_OPTIONAL);
const char *s = NULL;
/* Used by the display fucntion to format a line. */
static void crypt_entry (char *s, ssize_t l, MUTTMENU * menu, int num)
{
- crypt_key_t **key_table = (crypt_key_t **) menu->data;
+ cryptkey_t **cryptkey_table = (cryptkey_t **) menu->data;
crypt_entry_t entry;
- entry.key = key_table[num];
+ entry.key = cryptkey_table[num];
entry.num = num + 1;
m_strformat(s, l, COLS - SW, PgpEntryFormat, crypt_entry_fmt, &entry,
/* Compare two addresses and the keyid to be used for sorting. */
static int _crypt_compare_address (const void *a, const void *b)
{
- crypt_key_t **s = (crypt_key_t **) a;
- crypt_key_t **t = (crypt_key_t **) b;
+ cryptkey_t **s = (cryptkey_t **) a;
+ cryptkey_t **t = (cryptkey_t **) b;
int r;
if ((r = m_strcasecmp((*s)->uid, (*t)->uid)))
/* Compare two key IDs and the addresses to be used for sorting. */
static int _crypt_compare_keyid (const void *a, const void *b)
{
- crypt_key_t **s = (crypt_key_t **) a;
- crypt_key_t **t = (crypt_key_t **) b;
+ cryptkey_t **s = (cryptkey_t **) a;
+ cryptkey_t **t = (cryptkey_t **) b;
int r;
if ((r = m_strcasecmp(crypt_keyid (*s), crypt_keyid (*t))))
/* Compare 2 creation dates and the addresses. For sorting. */
static int _crypt_compare_date (const void *a, const void *b)
{
- crypt_key_t **s = (crypt_key_t **) a;
- crypt_key_t **t = (crypt_key_t **) b;
+ cryptkey_t **s = (cryptkey_t **) a;
+ cryptkey_t **t = (cryptkey_t **) b;
unsigned long ts = 0, tt = 0;
if ((*s)->kobj->subkeys && ((*s)->kobj->subkeys->timestamp > 0))
addresses and the key IDs. For sorting. */
static int _crypt_compare_trust (const void *a, const void *b)
{
- crypt_key_t **s = (crypt_key_t **) a;
- crypt_key_t **t = (crypt_key_t **) b;
+ cryptkey_t **s = (cryptkey_t **) a;
+ cryptkey_t **t = (cryptkey_t **) b;
unsigned long ts = 0, tt = 0;
int r;
}
typedef enum {
- KEY_CAP_CAN_ENCRYPT,
- KEY_CAP_CAN_SIGN,
- KEY_CAP_CAN_CERTIFY
+ 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;
/* Show detailed information about the selected key */
-static void verify_key (crypt_key_t * key)
+static void verify_key (cryptkey_t * key)
{
FILE *fp;
char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
while ((s = k->chain_id) && k->subkeys && m_strcmp(s, k->subkeys->fpr)) {
putc ('\n', fp);
err = gpgme_op_keylist_start (listctx, s, 0);
- gpgme_key_release (k);
+ gpgme_key_unref(k);
k = NULL;
if (!err)
err = gpgme_op_keylist_next (listctx, &k);
}
leave:
- gpgme_key_release (k);
+ gpgme_key_unref(k);
gpgme_release (listctx);
m_fclose(&fp);
mutt_clear_error ();
/* Implementation of `findkeys'. */
-/* Convert string_list_t into a pattern string suitable to be passed to GPGME.
- We need to convert spaces in an item into a '+' and '%' into
- "%25". */
-static char *list_to_pattern (string_list_t * list)
+static void add_hints(string_array *arr, const char *s)
{
- string_list_t *l;
- char *pattern, *p;
- const char *s;
- ssize_t n;
+ if (!s)
+ return;
- n = 0;
- for (l = list; l; l = l->next) {
- for (s = l->data; *s; s++) {
- if (*s == '%')
- n += 2;
- n++;
+ while (*s) {
+ int l = strcspn(s, " ,.:\"()<>\n");
+ string_array_append(arr, p_dupstr(s, l));
+ s += l;
+ s += strspn(s, " ,.:\"()<>\n");
}
- n++; /* delimiter or end of string */
- }
- n++; /* make sure to allocate at least one byte */
- pattern = p = p_new(char, 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 (string_list_t * hints, unsigned int app,
- int secret)
+/* Return a list of keys which are candidates for the selection. */
+static cryptkey_t *
+get_candidates(string_array *hints, unsigned int app, int secret)
{
- crypt_key_t *db, *k, **kend;
- char *pattern;
- gpgme_error_t err;
- gpgme_ctx_t ctx;
- gpgme_key_t key;
- int idx;
- gpgme_user_id_t uid = NULL;
-
- pattern = list_to_pattern (hints);
- if (!pattern)
- return NULL;
-
- err = gpgme_new (&ctx);
- if (err) {
- mutt_error (_("gpgme_new failed: %s"), gpgme_strerror (err));
- p_delete(&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. */
- string_list_t *l;
- ssize_t n;
- char **patarr;
+ cryptkey_t *res = NULL, **kend = &res;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ gpgme_key_t key;
- for (l = hints, n = 0; l; l = l->next) {
- if (l->data && *l->data)
- n++;
- }
- if (!n)
- goto no_pgphints;
+ if (hints->len <= 0)
+ return NULL;
+ string_array_append(hints, NULL);
+ ctx = create_gpgme_context(0);
- patarr = p_new(char *, n + 1);
- for (l = hints, n = 0; l; l = l->next) {
- if (l->data && *l->data)
- patarr[n++] = m_strdup(l->data);
- }
- patarr[n] = NULL;
- err = gpgme_op_keylist_ext_start (ctx, (const char **) patarr, secret, 0);
- for (n = 0; patarr[n]; n++)
- p_delete(&patarr[n]);
- p_delete(&patarr);
- if (err) {
- mutt_error (_("gpgme_op_keylist_start failed: %s"), gpgme_strerror (err));
- gpgme_release (ctx);
- p_delete(&pattern);
- return NULL;
- }
+ if ((app & APPLICATION_PGP)) {
+ err = gpgme_op_keylist_ext_start(ctx, (const char **)hints->arr,
+ secret, 0);
+ if (err) {
+ mutt_error(_("gpgme_op_keylist_start failed: %s"),
+ gpgme_strerror(err));
+ gpgme_release(ctx);
+ return NULL;
+ }
- 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;
-
- for (idx = 0, uid = key->uids; uid; idx++, uid = uid->next) {
- k = p_new(crypt_key_t, 1);
- k->kobj = key;
- k->idx = idx;
- k->uid = uid->uid;
- k->flags = flags;
- *kend = k;
- kend = &k->next;
- }
+ while (!(err = gpgme_op_keylist_next(ctx, &key))) {
+ gpgme_user_id_t uid = NULL;
+ unsigned int flags = 0;
+ int idx;
+
+ 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) {
+ cryptkey_t *k = p_new(cryptkey_t, 1);
+ 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);
}
- 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);
- p_delete(&pattern);
- return NULL;
- }
+ if ((app & APPLICATION_SMIME)) {
+ gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
+ err = gpgme_op_keylist_ext_start(ctx, (const char **)hints->arr,
+ secret, 0);
+ if (err) {
+ mutt_error(_("gpgme_op_keylist_start failed: %s"),
+ gpgme_strerror(err));
+ gpgme_release(ctx);
+ 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 = p_new(crypt_key_t, 1);
- k->kobj = key;
- k->idx = idx;
- k->uid = uid->uid;
- k->flags = flags;
- *kend = k;
- kend = &k->next;
- }
+ while (!(err = gpgme_op_keylist_next(ctx, &key))) {
+ gpgme_user_id_t uid = NULL;
+ unsigned int flags = KEYFLAG_ISX509;
+ int idx;
+
+ 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) {
+ cryptkey_t *k = p_new(cryptkey_t, 1);
+ 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);
}
- 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);
- p_delete(&pattern);
- return db;
-}
-
-/* Add the string STR to the list HINTS. This list is later used to
- match addresses. */
-static string_list_t *crypt_add_string_to_hints (string_list_t * hints, const char *str)
-{
- char *scratch;
- char *t;
-
- if ((scratch = m_strdup(str)) == NULL)
- return hints;
-
- for (t = strtok (scratch, " ,.:\"()<>\n"); t;
- t = strtok (NULL, " ,.:\"()<>\n")) {
- if (m_strlen(t) > 3)
- hints = mutt_add_list(hints, t);
- }
- p_delete(&scratch);
- return hints;
+ gpgme_release(ctx);
+ return res;
}
/* 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,
+static cryptkey_t *crypt_select_key (cryptkey_t * keys,
address_t * p, const char *s,
unsigned int app, int *forced_valid)
{
int keymax;
- crypt_key_t **key_table;
+ cryptkey_t **cryptkey_table;
MUTTMENU *menu;
int i, done = 0;
char helpstr[STRING], buf[LONG_STRING];
- crypt_key_t *k;
+ cryptkey_t *k;
int (*f) (const void *, const void *);
int menu_to_use = 0;
int unusable = 0;
/* build the key table */
keymax = i = 0;
- key_table = NULL;
+ cryptkey_table = NULL;
for (k = keys; k; k = k->next) {
if (!option (OPTPGPSHOWUNUSABLE) && (k->flags & KEYFLAG_CANTUSE)) {
unusable = 1;
if (i == keymax) {
keymax += 20;
- p_realloc(&key_table, keymax);
+ p_realloc(&cryptkey_table, keymax);
}
- key_table[i++] = k;
+ cryptkey_table[i++] = k;
}
if (!i && unusable) {
f = crypt_compare_trust;
break;
}
- qsort (key_table, i, sizeof (crypt_key_t *), f);
+ qsort (cryptkey_table, i, sizeof (cryptkey_t *), f);
if (app & APPLICATION_PGP)
menu_to_use = MENU_KEY_SELECT_PGP;
menu->make_entry = crypt_entry;
menu->menu = menu_to_use;
menu->help = helpstr;
- menu->data = key_table;
+ menu->data = cryptkey_table;
{
const char *ts;
*forced_valid = 0;
switch (mutt_menuLoop (menu)) {
case OP_VERIFY_KEY:
- verify_key (key_table[menu->current]);
+ verify_key (cryptkey_table[menu->current]);
menu->redraw = REDRAW_FULL;
break;
case OP_VIEW_ID:
- mutt_message ("%s", key_table[menu->current]->uid);
+ mutt_message ("%s", cryptkey_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.");
+ if (cryptkey_table[menu->current]->flags & KEYFLAG_CANTUSE ) {
+ 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]))) {
+ ((cryptkey_table[menu->current]->flags & KEYFLAG_CANTUSE)
+ || !crypt_id_is_strong (cryptkey_table[menu->current]))) {
const char *warn_s;
char buff[LONG_STRING];
- if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
+ if (cryptkey_table[menu->current]->flags & KEYFLAG_CANTUSE)
s = N_("ID is expired/disabled/revoked.");
else {
gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
warn_s = "??";
- uid = key_table[menu->current]->kobj->uids;
- for (j = 0; (j < key_table[menu->current]->idx) && uid;
+ uid = cryptkey_table[menu->current]->kobj->uids;
+ for (j = 0; (j < cryptkey_table[menu->current]->idx) && uid;
j++, uid = uid->next);
if (uid)
val = uid->validity;
}
}
- k = crypt_copy_key (key_table[menu->current]);
+ k = cryptkey_dup(cryptkey_table[menu->current]);
done = 1;
break;
}
mutt_menuDestroy (&menu);
- p_delete(&key_table);
+ p_delete(&cryptkey_table);
set_option (OPTNEEDREDRAW);
return k;
}
-static crypt_key_t *crypt_getkeybyaddr (address_t * a, short abilities,
+static cryptkey_t *crypt_getkeybyaddr (address_t * a, short abilities,
unsigned int app, int *forced_valid)
{
address_t *r, *p;
- string_list_t *hints = NULL;
int weak = 0;
int invalid = 0;
int this_key_has_invalid;
int match;
- crypt_key_t *keys, *k;
- crypt_key_t *the_valid_key = NULL;
- crypt_key_t *matches = NULL;
- crypt_key_t **matches_endp = &matches;
+ cryptkey_t *keys, *k;
+ cryptkey_t *the_valid_key = NULL;
+ cryptkey_t *matches = NULL;
+ cryptkey_t **matches_endp = &matches;
*forced_valid = 0;
- if (a && a->mailbox)
- hints = crypt_add_string_to_hints (hints, a->mailbox);
- if (a && a->personal)
- 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));
+ {
+ string_array hints;
+ string_array_init(&hints);
+ add_hints(&hints, a->mailbox);
+ add_hints(&hints, a->personal);
- string_list_wipe(&hints);
+ mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
+ keys = get_candidates(&hints, app, (abilities & KEYFLAG_CANSIGN));
+ string_array_wipe(&hints);
+ }
if (!keys)
return NULL;
address_list_wipe(&r);
if (match) {
- crypt_key_t *tmp;
+ cryptkey_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 = cryptkey_dup(k);
matches_endp = &tmp->next;
the_valid_key = tmp;
}
}
-
- crypt_free_key (&keys);
+ key_list_wipe(&keys);
if (matches) {
if (the_valid_key && !multi && !weak
*
* Proceed without asking the user.
*/
- k = crypt_copy_key (the_valid_key);
- }
- else {
+ k = cryptkey_dup(the_valid_key);
+ } else {
/*
* Else: Ask the user.
*/
k = crypt_select_key (matches, a, NULL, app, forced_valid);
}
- crypt_free_key (&matches);
- }
- else
+ key_list_wipe(&matches);
+ } else {
k = NULL;
+ }
return k;
}
-static crypt_key_t *crypt_getkeybystr (const char *p, short abilities,
+static cryptkey_t *crypt_getkeybystr (const char *p, short abilities,
unsigned int app, int *forced_valid)
{
- string_list_t *hints = NULL;
- crypt_key_t *keys;
- crypt_key_t *matches = NULL;
- crypt_key_t **matches_endp = &matches;
- crypt_key_t *k;
+ cryptkey_t *keys;
+ cryptkey_t *matches = NULL;
+ cryptkey_t **matches_endp = &matches;
+ cryptkey_t *k;
int match;
mutt_message (_("Looking for keys matching \"%s\"..."), p);
*forced_valid = 0;
- hints = crypt_add_string_to_hints (hints, p);
- keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
- string_list_wipe(&hints);
+ {
+ string_array hints;
+ string_array_init(&hints);
+ add_hints(&hints, p);
+ keys = get_candidates(&hints, app, (abilities & KEYFLAG_CANSIGN));
+ string_array_wipe(&hints);
+ }
if (!keys)
return NULL;
for (k = keys; k; k = k->next) {
+ const char *s = crypt_keyid(k);
+
if (abilities && !(k->flags & abilities))
continue;
match = 0;
- if (!*p || !m_strcasecmp(p, crypt_keyid (k))
- || (!m_strncasecmp(p, "0x", 2)
- && !m_strcasecmp(p + 2, crypt_keyid (k)))
- || (option (OPTPGPLONGIDS)
- && !m_strncasecmp(p, "0x", 2)
- && !m_strcasecmp(p + 2, crypt_keyid (k) + 8))
- || m_stristr(k->uid, p)) {
- crypt_key_t *tmp;
+ if (!*p || !m_strcasecmp(p, s)
+ || (!m_strncasecmp(p, "0x", 2) && !m_strcasecmp(p + 2, s))
+ || m_stristr(k->uid, p))
+ {
+ cryptkey_t *tmp;
- *matches_endp = tmp = crypt_copy_key (k);
+ *matches_endp = tmp = cryptkey_dup(k);
matches_endp = &tmp->next;
}
}
-
- crypt_free_key (&keys);
+ key_list_wipe(&keys);
if (matches) {
k = crypt_select_key (matches, NULL, p, app, forced_valid);
- crypt_free_key (&matches);
+ key_list_wipe(&matches);
return k;
}
return NULL;
}
-/* Display TAG as a prompt to ask for a key. If WHATFOR is not null
- use it as default and store it under that label as the next
- 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, short abilities,
- unsigned int app, int *forced_valid)
+/* Display TAG as a prompt to ask for a key.
+ * 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 cryptkey_t *
+crypt_ask_for_key(const char *tag, int abilities, int app, int *forced_valid)
{
- crypt_key_t *key;
- char resp[STRING];
- struct crypt_cache *l = NULL;
- int dummy;
+ cryptkey_t *key;
+ char resp[STRING];
+ int dummy;
- if (!forced_valid)
- forced_valid = &dummy;
+ if (!forced_valid)
+ forced_valid = &dummy;
+ *forced_valid = 0;
- mutt_clear_error ();
+ mutt_clear_error();
+ for (;;) {
+ resp[0] = 0;
+ if (mutt_get_field(tag, resp, sizeof(resp), M_CLEAR) != 0)
+ return NULL;
- *forced_valid = 0;
- resp[0] = 0;
- if (whatfor) {
- for (l = id_defaults; l; l = l->next)
- if (!m_strcasecmp(whatfor, l->what)) {
- m_strcpy(resp, sizeof(resp), NONULL(l->dflt));
- break;
- }
- }
+ if (m_strisempty(resp))
+ return NULL;
- for (;;) {
- resp[0] = 0;
- if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
- return NULL;
+ if ((key = crypt_getkeybystr(resp, abilities, app, forced_valid)))
+ return key;
- if (whatfor) {
- if (l)
- m_strreplace(&l->dflt, resp);
- else {
- l = p_new(struct crypt_cache, 1);
- l->next = id_defaults;
- id_defaults = l;
- l->what = m_strdup(whatfor);
- l->dflt = m_strdup(resp);
- }
+ BEEP ();
}
-
- 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_t * to, address_t * cc, address_t * bcc,
- unsigned int app)
+static char *find_keys(ENVELOPE *env, unsigned int app)
{
- char *keylist = NULL, *t;
- const char *keyID;
- ssize_t keylist_size = 0;
- ssize_t keylist_used = 0;
- address_t *tmp = NULL, *addr = NULL;
- address_t **last = &tmp;
- address_t *p, *q;
- int i;
- crypt_key_t *k_info, *key;
- const char *fqdn = mutt_fqdn (1);
+ address_t *lst = NULL, *addr;
+ buffer_t *keylist = buffer_new();
-#if 0
- *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 = address_list_dup (p);
- while (*last)
- last = &((*last)->next);
- }
-
- rfc822_qualify(tmp, fqdn);
- address_list_uniq(tmp);
-
- for (p = tmp; p; p = p->next) {
- char buf[LONG_STRING];
- int forced_valid = 0;
-
- q = p;
- k_info = NULL;
+ {
+ address_t **last = &lst;
+ *last = address_list_dup(env->to);
+ last = address_list_last(last);
+ *last = address_list_dup(env->cc);
+ last = address_list_last(last);
+ *last = address_list_dup(env->bcc);
+
+ rfc822_qualify(lst, mutt_fqdn(1));
+ address_list_uniq(lst);
+ }
+
+ while ((addr = address_list_pop(&lst))) {
+ char buf[STRING];
+ int forced_valid = 0;
+ const char *keyID;
+ cryptkey_t *key = NULL;
+
+ if ((keyID = mutt_crypt_hook(addr))) {
+ int r;
+
+ snprintf(buf, sizeof(buf), _("Use keyID = \"%s\" for %s?"), keyID,
+ addr->mailbox);
+ r = mutt_yesorno(buf, M_YES);
+
+ if (r == -1) {
+ address_list_wipe(&lst);
+ address_list_wipe(&addr);
+ buffer_delete(&keylist);
+ return NULL;
+ }
- if ((keyID = mutt_crypt_hook (p)) != NULL) {
- int r;
+ if (r == M_YES) {
+ address_t *a;
+ /* check for e-mail address */
+ if (strchr(keyID, '@') && (a = rfc822_parse_adrlist(NULL, keyID))) {
+ rfc822_qualify(a, mutt_fqdn(1));
+ address_list_wipe(&addr);
+ addr = a;
+ } else {
+ key = crypt_getkeybystr(keyID, KEYFLAG_CANENCRYPT, app,
+ &forced_valid);
+ }
+ }
+ }
- 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))) {
- rfc822_qualify(addr, fqdn);
- q = addr;
+ if (!key) {
+ key = crypt_getkeybyaddr(addr, KEYFLAG_CANENCRYPT, app, &forced_valid);
}
- else {
- k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT,
- app, &forced_valid);
+ if (!key) {
+ snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), addr->mailbox);
+ key = crypt_ask_for_key(buf, KEYFLAG_CANENCRYPT, app,
+ &forced_valid);
+ if (!key) {
+ address_list_wipe(&lst);
+ address_list_wipe(&addr);
+ buffer_delete(&keylist);
+ return NULL;
+ }
}
- }
- else if (r == -1) {
- p_delete(&keylist);
- address_list_wipe(&tmp);
- address_list_wipe(&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 (keylist->len)
+ buffer_addch(keylist, ' ');
+ buffer_addstr(keylist, "0x");
+ buffer_addstr(keylist, crypt_fpr(key));
+ if (forced_valid)
+ buffer_addch(keylist, '!');
- if ((key = crypt_ask_for_key (buf, q->mailbox, KEYFLAG_CANENCRYPT, app,
- &forced_valid)) == NULL)
- {
- p_delete(&keylist);
- address_list_wipe(&tmp);
+ key_list_wipe(&key);
address_list_wipe(&addr);
- return NULL;
- }
- }
- else
- key = k_info;
-
- {
- const char *s = crypt_fpr (key);
-
- keylist_size += m_strlen(s) + 4 + 1;
- p_realloc(&keylist, keylist_size);
- sprintf (keylist + keylist_used, "%s0x%s%s",
- keylist_used ? " " : "", s, forced_valid ? "!" : "");
}
- keylist_used = m_strlen(keylist);
- crypt_free_key (&key);
- address_list_wipe(&addr);
- }
- address_list_wipe(&tmp);
- return (keylist);
+ address_list_wipe(&lst);
+ return buffer_unwrap(&keylist);
}
-int crypt_get_keys (HEADER * msg, char **keylist)
+int crypt_get_keys(HEADER *msg, char **keylist)
{
- /* Do a quick check to make sure that we can find all of the encryption
- * keys if the user has requested this service.
- */
+ /* Do a quick check to make sure that we can find all of the encryption
+ * keys if the user has requested this service.
+ */
- *keylist = NULL;
+ *keylist = NULL;
- if (msg->security & ENCRYPT) {
- if (msg->security & APPLICATION_PGP) {
- set_option(OPTPGPCHECKTRUST);
- *keylist = find_keys(msg->env->to, msg->env->cc, msg->env->bcc,
- APPLICATION_PGP);
- unset_option(OPTPGPCHECKTRUST);
- if (!*keylist)
- return -1;
- }
+ if (msg->security & ENCRYPT) {
+ if (msg->security & APPLICATION_PGP) {
+ set_option(OPTPGPCHECKTRUST);
+ *keylist = find_keys(msg->env, APPLICATION_PGP);
+ unset_option(OPTPGPCHECKTRUST);
+ if (!*keylist)
+ return -1;
+ }
- if (msg->security & APPLICATION_SMIME) {
- *keylist = find_keys(msg->env->to, msg->env->cc, msg->env->bcc,
- APPLICATION_SMIME);
- if (!*keylist)
- return -1;
+ if (msg->security & APPLICATION_SMIME) {
+ *keylist = find_keys(msg->env, APPLICATION_SMIME);
+ if (!*keylist)
+ return -1;
+ }
}
- }
- return (0);
+ return 0;
}
int crypt_send_menu (HEADER * msg, int *redraw, int is_smime)
{
- crypt_key_t *p;
- char input_signas[STRING];
- int choice;
+ cryptkey_t *p;
+ char buf[STRING];
+ int choice;
+
+ if (msg->security & APPLICATION_SMIME)
+ is_smime = 1;
+ if (msg->security & APPLICATION_PGP)
+ is_smime = 0;
+
+ choice = is_smime
+ ? mutt_multi_choice(_("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
+ _("esabpc"))
+ : mutt_multi_choice(_("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
+ _("esabmc"));
+
+ switch (choice) {
+ case 1: /* (e)ncrypt */
+ msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
+ msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
+ break;
- if (msg->security & APPLICATION_PGP)
- is_smime = 0;
- else if (msg->security & APPLICATION_SMIME)
- is_smime = 1;
+ case 2: /* (s)ign */
+ msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
+ msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
+ break;
- if (is_smime)
- choice =
- mutt_multi_choice (_
- ("S/MIME (e)ncrypt, (s)ign, sign (a)s, (b)oth, (p)gp or (c)lear?"),
- _("esabpc"));
- else
- choice =
- mutt_multi_choice (_
- ("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?"),
- _("esabmc"));
-
- switch (choice) {
- case 1: /* (e)ncrypt */
- msg->security |= (is_smime ? SMIMEENCRYPT : PGPENCRYPT);
- msg->security &= ~(is_smime ? SMIMESIGN : PGPSIGN);
- break;
+ case 3: /* sign (a)s */
+ p = crypt_ask_for_key(_("Sign as: "), KEYFLAG_CANSIGN,
+ is_smime ? APPLICATION_SMIME : APPLICATION_PGP,
+ NULL);
+ if (p) {
+ snprintf(buf, sizeof(buf), "0x%s", crypt_keyid(p));
+ m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs, buf);
+ key_list_wipe(&p);
+ msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
+ }
+ *redraw = REDRAW_FULL;
+ break;
- case 2: /* (s)ign */
- msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
- msg->security &= ~(is_smime ? SMIMEENCRYPT : PGPENCRYPT);
- break;
+ case 4: /* (b)oth */
+ if (is_smime) {
+ msg->security = SMIMEENCRYPT | SMIMESIGN;
+ } else {
+ msg->security = PGPENCRYPT | PGPSIGN;
+ }
+ break;
- case 3: /* sign (a)s */
- if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
- is_smime ? APPLICATION_SMIME :
- APPLICATION_PGP, NULL)))
- {
- snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
- m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
- input_signas);
- crypt_free_key (&p);
+ case 5: /* (p)gp or s/(m)ime */
+ is_smime = !is_smime;
+ break;
- msg->security |= (is_smime ? SMIMESIGN : PGPSIGN);
+ case 6: /* (c)lear */
+ return msg->security = 0;
}
- *redraw = REDRAW_FULL;
- break;
-
- case 4: /* (b)oth */
- msg->security =
- (is_smime ? (SMIMEENCRYPT | SMIMESIGN) : (PGPENCRYPT | PGPSIGN));
- break;
-
- case 5: /* (p)gp or s/(m)ime */
- is_smime = !is_smime;
- break;
-
- case 6: /* (c)lear */
- return msg->security = 0;
- }
- if (is_smime) {
- msg->security &= ~APPLICATION_PGP;
- msg->security |= APPLICATION_SMIME;
- } else {
- msg->security &= ~APPLICATION_SMIME;
- msg->security |= APPLICATION_PGP;
- }
+ if (is_smime) {
+ msg->security &= ~APPLICATION_PGP;
+ msg->security |= APPLICATION_SMIME;
+ } else {
+ msg->security &= ~APPLICATION_SMIME;
+ msg->security |= APPLICATION_PGP;
+ }
- return msg->security;
+ return msg->security;
}
-int crypt_smime_verify_sender (HEADER * h)
+int crypt_smime_verify_sender(HEADER *h)
{
- address_t *sender = NULL;
- unsigned int ret = 1;
+ address_t *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 = m_strlen(sender->mailbox);
- for (uid = key->uids; uid && ret; uid = uid->next) {
- uid_length = m_strlen(uid->email);
- if (1 && (uid->email[0] == '<')
- && (uid->email[uid_length - 1] == '>')
- && (uid_length == sender_length + 2)
- && (!m_strncmp (uid->email + 1, sender->mailbox, sender_length)))
- ret = 0;
- }
+ if (!sender) {
+ mutt_any_key_to_continue ("Failed to figure out sender");
+ goto end;
}
- 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_t key = signature_key;
+ gpgme_user_id_t uid = NULL;
+ int sender_length = 0;
+ int uid_length = 0;
+
+ sender_length = m_strlen(sender->mailbox);
+ for (uid = key->uids; uid && ret; uid = uid->next) {
+ uid_length = m_strlen(uid->email);
+ if (1 && (uid->email[0] == '<')
+ && (uid->email[uid_length - 1] == '>')
+ && (uid_length == sender_length + 2)
+ && (!m_strncmp (uid->email + 1, sender->mailbox, sender_length)))
+ ret = 0;
+ }
+ } else {
+ mutt_any_key_to_continue ("Failed to verify sender");
+ }
- return ret;
+ end:
+ if (signature_key) {
+ gpgme_key_unref(signature_key);
+ signature_key = NULL;
+ }
+ return ret;
}
static void crypt_invoke_import(FILE *stream, int smime)