NeoMutt  2020-08-07-1-gab41a1
Teaching an old dog new tricks
DOXYGEN
pgp.h File Reference

PGP sign, encrypt, check routines. More...

#include <stdbool.h>
#include <stdio.h>
#include "lib.h"
+ Include dependency graph for pgp.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool pgp_use_gpg_agent (void)
 Does the user want to use the gpg agent? More...
 
int pgp_class_check_traditional (FILE *fp, struct Body *b, bool just_one)
 Implements CryptModuleSpecs::pgp_check_traditional() More...
 
char * pgp_this_keyid (struct PgpKeyInfo *k)
 Get the ID of this key. More...
 
char * pgp_keyid (struct PgpKeyInfo *k)
 Get the ID of the main (parent) key. More...
 
char * pgp_short_keyid (struct PgpKeyInfo *k)
 Get a key's short id. More...
 
char * pgp_long_keyid (struct PgpKeyInfo *k)
 Get a key's long id. More...
 
char * pgp_fpr_or_lkeyid (struct PgpKeyInfo *k)
 Get the fingerprint or long keyid. More...
 
int pgp_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() More...
 
char * pgp_class_find_keys (struct AddressList *addrlist, bool oppenc_mode)
 Implements CryptModuleSpecs::find_keys() More...
 
int pgp_class_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() More...
 
int pgp_class_encrypted_handler (struct Body *a, struct State *s)
 Implements CryptModuleSpecs::encrypted_handler() More...
 
void pgp_class_extract_key_from_attachment (FILE *fp, struct Body *top)
 Implements CryptModuleSpecs::pgp_extract_key_from_attachment() More...
 
void pgp_class_void_passphrase (void)
 Implements CryptModuleSpecs::void_passphrase() More...
 
bool pgp_class_valid_passphrase (void)
 Implements CryptModuleSpecs::valid_passphrase() More...
 
int pgp_class_verify_one (struct Body *sigbdy, struct State *s, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() More...
 
struct Bodypgp_class_traditional_encryptsign (struct Body *a, SecurityFlags flags, char *keylist)
 Implements CryptModuleSpecs::pgp_traditional_encryptsign() More...
 
struct Bodypgp_class_encrypt_message (struct Body *a, char *keylist, bool sign, const struct AddressList *from)
 Implements CryptModuleSpecs::pgp_encrypt_message() More...
 
struct Bodypgp_class_sign_message (struct Body *a, const struct AddressList *from)
 Implements CryptModuleSpecs::sign_message() More...
 
int pgp_class_send_menu (struct Email *e)
 Implements CryptModuleSpecs::send_menu() More...
 

Detailed Description

PGP sign, encrypt, check routines.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • g10 Code GmbH
  • Pietro Cerutti

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, see http://www.gnu.org/licenses/.

Definition in file pgp.h.

Function Documentation

◆ pgp_use_gpg_agent()

bool pgp_use_gpg_agent ( void  )

Does the user want to use the gpg agent?

Return values
trueIf they do
Note
This functions sets the environment variable $GPG_TTY

Definition at line 117 of file pgp.c.

118 {
119  char *tty = NULL;
120 
121  /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
122  if (!C_PgpUseGpgAgent)
123  return false;
124 
125  tty = ttyname(0);
126  if (tty)
127  {
128  setenv("GPG_TTY", tty, 0);
129  mutt_envlist_set("GPG_TTY", tty, false);
130  }
131 
132  return true;
133 }
bool C_PgpUseGpgAgent
Config: Use a PGP agent for caching passwords.
Definition: config.c:75
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_class_check_traditional()

int pgp_class_check_traditional ( FILE *  fp,
struct Body b,
bool  just_one 
)

Implements CryptModuleSpecs::pgp_check_traditional()

Definition at line 833 of file pgp.c.

834 {
835  int rc = 0;
836  int r;
837  for (; b; b = b->next)
838  {
839  if (!just_one && is_multipart(b))
840  rc = pgp_class_check_traditional(fp, b->parts, false) || rc;
841  else if (b->type == TYPE_TEXT)
842  {
844  if (r)
845  rc = rc || r;
846  else
847  rc = pgp_check_traditional_one_body(fp, b) || rc;
848  }
849 
850  if (just_one)
851  break;
852  }
853 
854  return rc;
855 }
#define is_multipart(body)
Definition: mime.h:82
struct Body * next
next attachment in the list
Definition: body.h:53
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
int pgp_class_check_traditional(FILE *fp, struct Body *b, bool just_one)
Implements CryptModuleSpecs::pgp_check_traditional()
Definition: pgp.c:833
Type: &#39;text/*&#39;.
Definition: mime.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
static int pgp_check_traditional_one_body(FILE *fp, struct Body *b)
Check the body of an inline PGP message.
Definition: pgp.c:766
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_this_keyid()

char* pgp_this_keyid ( struct PgpKeyInfo k)

Get the ID of this key.

Parameters
kPGP key
Return values
ptrLong/Short key id string
Note
The string returned depends on $pgp_long_ids

Definition at line 179 of file pgp.c.

180 {
181  if (C_PgpLongIds)
182  return k->keyid;
183  return k->keyid + 8;
184 }
char * keyid
Definition: pgplib.h:48
bool C_PgpLongIds
Config: Display long PGP key IDs to the user.
Definition: config.c:48
+ Here is the caller graph for this function:

◆ pgp_keyid()

char* pgp_keyid ( struct PgpKeyInfo k)

Get the ID of the main (parent) key.

Parameters
kPGP key
Return values
ptrLong/Short key id string

Definition at line 191 of file pgp.c.

192 {
193  k = key_parent(k);
194 
195  return pgp_this_keyid(k);
196 }
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key&#39;s parent (if it&#39;s a subkey)
Definition: pgp.c:140
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:179
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_short_keyid()

char* pgp_short_keyid ( struct PgpKeyInfo k)

Get a key's short id.

Parameters
kPGP key
Return values
ptrShort key id string

Definition at line 165 of file pgp.c.

166 {
167  k = key_parent(k);
168 
169  return k->keyid + 8;
170 }
char * keyid
Definition: pgplib.h:48
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key&#39;s parent (if it&#39;s a subkey)
Definition: pgp.c:140
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_long_keyid()

char* pgp_long_keyid ( struct PgpKeyInfo k)

Get a key's long id.

Parameters
kPGP key
Return values
ptrLong key id string

Definition at line 153 of file pgp.c.

154 {
155  k = key_parent(k);
156 
157  return k->keyid;
158 }
char * keyid
Definition: pgplib.h:48
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key&#39;s parent (if it&#39;s a subkey)
Definition: pgp.c:140
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_fpr_or_lkeyid()

char* pgp_fpr_or_lkeyid ( struct PgpKeyInfo k)

Get the fingerprint or long keyid.

Parameters
kPGP key
Return values
ptrString fingerprint or long keyid

Grab the longest key identifier available: fingerprint or else the long keyid.

The longest available should be used for internally identifying the key and for invoking pgp commands.

Definition at line 221 of file pgp.c.

222 {
223  char *fingerprint = pgp_fingerprint(k);
224  return fingerprint ? fingerprint : pgp_long_keyid(k);
225 }
static char * pgp_fingerprint(struct PgpKeyInfo *k)
Get the key&#39;s fingerprint.
Definition: pgp.c:203
char * fingerprint
Definition: pgplib.h:49
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key&#39;s long id.
Definition: pgp.c:153
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_class_decrypt_mime()

int pgp_class_decrypt_mime ( FILE *  fp_in,
FILE **  fp_out,
struct Body b,
struct Body **  cur 
)

Implements CryptModuleSpecs::decrypt_mime()

Definition at line 1111 of file pgp.c.

1112 {
1113  struct State s = { 0 };
1114  struct Body *p = b;
1115  bool need_decode = false;
1116  int saved_type = 0;
1117  LOFF_T saved_offset = 0;
1118  size_t saved_length = 0;
1119  FILE *fp_decoded = NULL;
1120  int rc = 0;
1121 
1123  {
1124  b = b->parts->next;
1125  /* Some clients improperly encode the octetstream part. */
1126  if (b->encoding != ENC_7BIT)
1127  need_decode = true;
1128  }
1130  {
1131  b = b->parts->next->next;
1132  need_decode = true;
1133  }
1134  else
1135  return -1;
1136 
1137  s.fp_in = fp_in;
1138 
1139  if (need_decode)
1140  {
1141  saved_type = b->type;
1142  saved_offset = b->offset;
1143  saved_length = b->length;
1144 
1145  fp_decoded = mutt_file_mkstemp();
1146  if (!fp_decoded)
1147  {
1148  mutt_perror(_("Can't create temporary file"));
1149  return -1;
1150  }
1151 
1152  fseeko(s.fp_in, b->offset, SEEK_SET);
1153  s.fp_out = fp_decoded;
1154 
1155  mutt_decode_attachment(b, &s);
1156 
1157  fflush(fp_decoded);
1158  b->length = ftello(fp_decoded);
1159  b->offset = 0;
1160  rewind(fp_decoded);
1161  s.fp_in = fp_decoded;
1162  s.fp_out = 0;
1163  }
1164 
1165  *fp_out = mutt_file_mkstemp();
1166  if (!*fp_out)
1167  {
1168  mutt_perror(_("Can't create temporary file"));
1169  rc = -1;
1170  goto bail;
1171  }
1172 
1173  *cur = pgp_decrypt_part(b, &s, *fp_out, p);
1174  if (!*cur)
1175  rc = -1;
1176  rewind(*fp_out);
1177 
1178 bail:
1179  if (need_decode)
1180  {
1181  b->type = saved_type;
1182  b->length = saved_length;
1183  b->offset = saved_offset;
1184  mutt_file_fclose(&fp_decoded);
1185  }
1186 
1187  return rc;
1188 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:471
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
static struct Body * pgp_decrypt_part(struct Body *a, struct State *s, FILE *fp_out, struct Body *p)
Decrypt part of a PGP message.
Definition: pgp.c:984
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:508
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Keep track when processing files.
Definition: state.h:44
+ Here is the call graph for this function:

◆ pgp_class_find_keys()

char* pgp_class_find_keys ( struct AddressList *  addrlist,
bool  oppenc_mode 
)

Implements CryptModuleSpecs::find_keys()

Definition at line 1413 of file pgp.c.

1414 {
1415  struct ListHead crypt_hook_list = STAILQ_HEAD_INITIALIZER(crypt_hook_list);
1416  struct ListNode *crypt_hook = NULL;
1417  const char *keyid = NULL;
1418  char *keylist = NULL;
1419  size_t keylist_size = 0;
1420  size_t keylist_used = 0;
1421  struct Address *p = NULL;
1422  struct PgpKeyInfo *k_info = NULL;
1423  const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
1424  char buf[1024];
1425  bool key_selected;
1426  struct AddressList hookal = TAILQ_HEAD_INITIALIZER(hookal);
1427 
1428  struct Address *a = NULL;
1429  TAILQ_FOREACH(a, addrlist, entries)
1430  {
1431  key_selected = false;
1432  mutt_crypt_hook(&crypt_hook_list, a);
1433  crypt_hook = STAILQ_FIRST(&crypt_hook_list);
1434  do
1435  {
1436  p = a;
1437  k_info = NULL;
1438 
1439  if (crypt_hook)
1440  {
1441  keyid = crypt_hook->data;
1442  enum QuadOption ans = MUTT_YES;
1443  if (!oppenc_mode && C_CryptConfirmhook)
1444  {
1445  snprintf(buf, sizeof(buf), _("Use keyID = \"%s\" for %s?"), keyid, p->mailbox);
1446  ans = mutt_yesorno(buf, MUTT_YES);
1447  }
1448  if (ans == MUTT_YES)
1449  {
1450  if (crypt_is_numerical_keyid(keyid))
1451  {
1452  if (mutt_strn_equal(keyid, "0x", 2))
1453  keyid += 2;
1454  goto bypass_selection; /* you don't see this. */
1455  }
1456 
1457  /* check for e-mail address */
1458  mutt_addrlist_clear(&hookal);
1459  if (strchr(keyid, '@') && (mutt_addrlist_parse(&hookal, keyid) != 0))
1460  {
1461  mutt_addrlist_qualify(&hookal, fqdn);
1462  p = TAILQ_FIRST(&hookal);
1463  }
1464  else if (!oppenc_mode)
1465  {
1467  }
1468  }
1469  else if (ans == MUTT_NO)
1470  {
1471  if (key_selected || STAILQ_NEXT(crypt_hook, entries))
1472  {
1473  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
1474  continue;
1475  }
1476  }
1477  else if (ans == MUTT_ABORT)
1478  {
1479  FREE(&keylist);
1480  mutt_addrlist_clear(&hookal);
1481  mutt_list_free(&crypt_hook_list);
1482  return NULL;
1483  }
1484  }
1485 
1486  if (!k_info)
1487  {
1489  k_info = pgp_getkeybyaddr(p, KEYFLAG_CANENCRYPT, PGP_PUBRING, oppenc_mode);
1490  }
1491 
1492  if (!k_info && !oppenc_mode)
1493  {
1494  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), p->mailbox);
1496  }
1497 
1498  if (!k_info)
1499  {
1500  FREE(&keylist);
1501  mutt_addrlist_clear(&hookal);
1502  mutt_list_free(&crypt_hook_list);
1503  return NULL;
1504  }
1505 
1506  keyid = pgp_fpr_or_lkeyid(k_info);
1507 
1508  bypass_selection:
1509  keylist_size += mutt_str_len(keyid) + 4;
1510  mutt_mem_realloc(&keylist, keylist_size);
1511  sprintf(keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", keyid);
1512  keylist_used = mutt_str_len(keylist);
1513 
1514  key_selected = true;
1515 
1516  pgp_key_free(&k_info);
1517  mutt_addrlist_clear(&hookal);
1518 
1519  if (crypt_hook)
1520  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
1521 
1522  } while (crypt_hook);
1523 
1524  mutt_list_free(&crypt_hook_list);
1525  }
1526  return keylist;
1527 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
User aborted the question (with Ctrl-G)
Definition: quad.h:38
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1347
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:135
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
Information about a PGP key.
Definition: pgplib.h:46
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
void mutt_crypt_hook(struct ListHead *list, struct Address *addr)
Find crypto hooks for an Address.
Definition: hook.c:746
void pgp_key_free(struct PgpKeyInfo **kpp)
Free a PGP key info.
Definition: pgplib.c:199
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
struct PgpKeyInfo * pgp_getkeybyaddr(struct Address *a, KeyFlags abilities, enum PgpRing keyring, bool oppenc_mode)
Find a PGP key by address.
Definition: pgpkey.c:361
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
Public keys.
Definition: pgpkey.h:39
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:598
char * pgp_fpr_or_lkeyid(struct PgpKeyInfo *k)
Get the fingerprint or long keyid.
Definition: pgp.c:221
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1181
char * data
String.
Definition: list.h:36
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition: pgpkey.c:495
bool C_CryptConfirmhook
Config: Prompt the user to confirm keys before use.
Definition: config.c:40
#define FREE(x)
Definition: memory.h:40
struct PgpKeyInfo * pgp_ask_for_key(char *tag, char *whatfor, KeyFlags abilities, enum PgpRing keyring)
Ask the user for a PGP key.
Definition: pgpkey.c:189
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
#define STAILQ_FIRST(head)
Definition: queue.h:347
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
void pgp_class_invoke_getkeys(struct Address *addr)
Implements CryptModuleSpecs::pgp_invoke_getkeys()
Definition: pgpinvoke.c:416
+ Here is the call graph for this function:

◆ pgp_class_application_handler()

int pgp_class_application_handler ( struct Body m,
struct State s 
)

Implements CryptModuleSpecs::application_handler()

Definition at line 450 of file pgp.c.

451 {
452  bool could_not_decrypt = false;
453  int decrypt_okay_rc = 0;
454  int needpass = -1;
455  bool pgp_keyblock = false;
456  bool clearsign = false;
457  int rc = -1;
458  int c = 1;
459  long bytes;
460  LOFF_T last_pos, offset;
461  char buf[8192];
462  FILE *fp_pgp_out = NULL, *fp_pgp_in = NULL, *fp_pgp_err = NULL;
463  FILE *fp_tmp = NULL;
464  pid_t pid;
465  struct Buffer *tmpfname = mutt_buffer_pool_get();
466 
467  bool maybe_goodsig = true;
468  bool have_any_sigs = false;
469 
470  char *gpgcharset = NULL;
471  char body_charset[256];
472  mutt_body_get_charset(m, body_charset, sizeof(body_charset));
473 
474  fseeko(s->fp_in, m->offset, SEEK_SET);
475  last_pos = m->offset;
476 
477  for (bytes = m->length; bytes > 0;)
478  {
479  if (!fgets(buf, sizeof(buf), s->fp_in))
480  break;
481 
482  offset = ftello(s->fp_in);
483  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
484  last_pos = offset;
485 
486  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
487  if (plen != 0)
488  {
489  clearsign = false;
490  could_not_decrypt = false;
491  decrypt_okay_rc = 0;
492 
493  if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
494  needpass = 1;
495  else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
496  {
497  clearsign = true;
498  needpass = 0;
499  }
500  else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
501  {
502  needpass = 0;
503  pgp_keyblock = true;
504  }
505  else
506  {
507  /* XXX we may wish to recode here */
508  if (s->prefix)
509  state_puts(s, s->prefix);
510  state_puts(s, buf);
511  continue;
512  }
513 
514  have_any_sigs = have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY));
515 
516  /* Copy PGP material to temporary file */
517  mutt_buffer_mktemp(tmpfname);
518  fp_tmp = mutt_file_fopen(mutt_b2s(tmpfname), "w+");
519  if (!fp_tmp)
520  {
521  mutt_perror(mutt_b2s(tmpfname));
522  FREE(&gpgcharset);
523  goto out;
524  }
525 
526  fputs(buf, fp_tmp);
527  while ((bytes > 0) && fgets(buf, sizeof(buf) - 1, s->fp_in))
528  {
529  offset = ftello(s->fp_in);
530  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
531  last_pos = offset;
532 
533  fputs(buf, fp_tmp);
534 
535  if ((needpass && mutt_str_equal("-----END PGP MESSAGE-----\n", buf)) ||
536  (!needpass &&
537  (mutt_str_equal("-----END PGP SIGNATURE-----\n", buf) ||
538  mutt_str_equal("-----END PGP PUBLIC KEY BLOCK-----\n", buf))))
539  {
540  break;
541  }
542  /* remember optional Charset: armor header as defined by RFC4880 */
543  if (mutt_str_startswith(buf, "Charset: "))
544  {
545  size_t l = 0;
546  FREE(&gpgcharset);
547  gpgcharset = mutt_str_dup(buf + 9);
548  l = mutt_str_len(gpgcharset);
549  if ((l > 0) && (gpgcharset[l - 1] == '\n'))
550  gpgcharset[l - 1] = 0;
551  if (!mutt_ch_check_charset(gpgcharset, false))
552  mutt_str_replace(&gpgcharset, "UTF-8");
553  }
554  }
555 
556  /* leave fp_tmp open in case we still need it - but flush it! */
557  fflush(fp_tmp);
558 
559  /* Invoke PGP if needed */
560  if (!clearsign || (s->flags & MUTT_VERIFY))
561  {
562  fp_pgp_out = mutt_file_mkstemp();
563  if (!fp_pgp_out)
564  {
565  mutt_perror(_("Can't create temporary file"));
566  goto out;
567  }
568 
569  fp_pgp_err = mutt_file_mkstemp();
570  if (!fp_pgp_err)
571  {
572  mutt_perror(_("Can't create temporary file"));
573  goto out;
574  }
575 
576  pid = pgp_invoke_decode(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
577  fileno(fp_pgp_err), mutt_b2s(tmpfname), (needpass != 0));
578  if (pid == -1)
579  {
580  mutt_file_fclose(&fp_pgp_out);
581  maybe_goodsig = false;
582  fp_pgp_in = NULL;
584  s, _("[-- Error: unable to create PGP subprocess --]\n"));
585  }
586  else /* PGP started successfully */
587  {
588  if (needpass)
589  {
592  if (pgp_use_gpg_agent())
593  *PgpPass = '\0';
594  fprintf(fp_pgp_in, "%s\n", PgpPass);
595  }
596 
597  mutt_file_fclose(&fp_pgp_in);
598 
599  int wait_filter_rc = filter_wait(pid);
600 
601  fflush(fp_pgp_err);
602  /* If we are expecting an encrypted message, verify status fd output.
603  * Note that BEGIN PGP MESSAGE does not guarantee the content is encrypted,
604  * so we need to be more selective about the value of decrypt_okay_rc.
605  *
606  * -3 indicates we actively found a DECRYPTION_FAILED.
607  * -2 and -1 indicate part or all of the content was plaintext. */
608  if (needpass)
609  {
610  rewind(fp_pgp_err);
611  decrypt_okay_rc = pgp_check_decryption_okay(fp_pgp_err);
612  if (decrypt_okay_rc <= -3)
613  mutt_file_fclose(&fp_pgp_out);
614  }
615 
616  if (s->flags & MUTT_DISPLAY)
617  {
618  rewind(fp_pgp_err);
619  crypt_current_time(s, "PGP");
620  int checksig_rc = pgp_copy_checksig(fp_pgp_err, s->fp_out);
621 
622  if (checksig_rc == 0)
623  have_any_sigs = true;
624  /* Sig is bad if
625  * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
626  * Sig _is_ correct if
627  * gpg_good_sign="" && pgp_decode_command returned 0 */
628  if (checksig_rc == -1 || (wait_filter_rc != 0))
629  maybe_goodsig = false;
630 
631  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
632  }
633  if (pgp_use_gpg_agent())
635  }
636 
637  /* treat empty result as sign of failure */
638  /* TODO: maybe on failure neomutt should include the original undecoded text. */
639  if (fp_pgp_out)
640  {
641  rewind(fp_pgp_out);
642  c = fgetc(fp_pgp_out);
643  ungetc(c, fp_pgp_out);
644  }
645  if (!clearsign && (!fp_pgp_out || (c == EOF)))
646  {
647  could_not_decrypt = true;
649  }
650 
651  if ((could_not_decrypt || (decrypt_okay_rc <= -3)) && !(s->flags & MUTT_DISPLAY))
652  {
653  mutt_error(_("Could not decrypt PGP message"));
654  goto out;
655  }
656  }
657 
658  /* Now, copy cleartext to the screen. */
659  if (s->flags & MUTT_DISPLAY)
660  {
661  if (needpass)
662  state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
663  else if (pgp_keyblock)
664  state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
665  else
666  state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
667  }
668 
669  if (clearsign)
670  {
671  rewind(fp_tmp);
672  pgp_copy_clearsigned(fp_tmp, s, body_charset);
673  }
674  else if (fp_pgp_out)
675  {
676  struct FgetConv *fc = NULL;
677  int ch;
678  char *expected_charset = (gpgcharset && *gpgcharset) ? gpgcharset : "utf-8";
679 
680  mutt_debug(LL_DEBUG3, "pgp: recoding inline from [%s] to [%s]\n",
681  expected_charset, C_Charset);
682 
683  rewind(fp_pgp_out);
684  state_set_prefix(s);
685  fc = mutt_ch_fgetconv_open(fp_pgp_out, expected_charset, C_Charset, MUTT_ICONV_HOOK_FROM);
686  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
687  state_prefix_putc(s, ch);
689  }
690 
691  /* Multiple PGP blocks can exist, so these need to be closed and
692  * unlinked inside the loop. */
693  mutt_file_fclose(&fp_tmp);
694  mutt_file_unlink(mutt_b2s(tmpfname));
695  mutt_file_fclose(&fp_pgp_out);
696  mutt_file_fclose(&fp_pgp_err);
697 
698  if (s->flags & MUTT_DISPLAY)
699  {
700  state_putc(s, '\n');
701  if (needpass)
702  {
703  state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
704  if (could_not_decrypt || (decrypt_okay_rc <= -3))
705  mutt_error(_("Could not decrypt PGP message"));
706  else if (decrypt_okay_rc < 0)
707  {
708  /* L10N: You will see this error message if (1) you are decrypting
709  (not encrypting) something and (2) it is a plaintext. So the
710  message does not mean "You failed to encrypt the message." */
711  mutt_error(_("PGP message is not encrypted"));
712  }
713  else
714  mutt_message(_("PGP message successfully decrypted"));
715  }
716  else if (pgp_keyblock)
717  state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
718  else
719  state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
720  }
721  }
722  else
723  {
724  /* A traditional PGP part may mix signed and unsigned content */
725  /* XXX we may wish to recode here */
726  if (s->prefix)
727  state_puts(s, s->prefix);
728  state_puts(s, buf);
729  }
730  }
731 
732  rc = 0;
733 
734 out:
735  m->goodsig = (maybe_goodsig && have_any_sigs);
736 
737  if (fp_tmp)
738  {
739  mutt_file_fclose(&fp_tmp);
740  mutt_file_unlink(mutt_b2s(tmpfname));
741  }
742  mutt_file_fclose(&fp_pgp_out);
743  mutt_file_fclose(&fp_pgp_err);
744 
745  mutt_buffer_pool_release(&tmpfname);
746 
747  FREE(&gpgcharset);
748 
749  if (needpass == -1)
750  {
752  s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
753  return -1;
754  }
755 
756  return rc;
757 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define state_puts(STATE, STR)
Definition: state.h:55
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:908
#define mutt_message(...)
Definition: logging.h:83
static int pgp_check_decryption_okay(FILE *fp_in)
Check GPG output for status codes.
Definition: pgp.c:338
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
char PgpPass[1024]
Definition: pgp.c:69
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
bool mutt_ch_check_charset(const char *cs, bool strict)
Does iconv understand a character set?
Definition: charset.c:818
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: pgp.c:75
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:71
pid_t pgp_invoke_decode(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname, bool need_passphrase)
Use PGP to decode a message.
Definition: pgpinvoke.c:246
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
#define mutt_b2s(buf)
Definition: buffer.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:75
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:165
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define MUTT_VERIFY
Perform signature verification.
Definition: state.h:33
static void pgp_copy_clearsigned(FILE *fp_in, struct State *s, char *charset)
Copy a clearsigned message, stripping the signature.
Definition: pgp.c:401
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:117
#define mutt_file_mkstemp()
Definition: file.h:106
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
#define state_set_prefix(state)
Definition: state.h:53
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
#define mutt_error(...)
Definition: logging.h:84
void state_prefix_putc(struct State *s, char c)
Write a prefixed character to the state.
Definition: state.c:131
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define state_putc(STATE, STR)
Definition: state.h:56
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:858
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:130
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
Log at debug level 3.
Definition: logging.h:42
bool pgp_class_valid_passphrase(void)
Implements CryptModuleSpecs::valid_passphrase()
Definition: pgp.c:84
static int pgp_copy_checksig(FILE *fp_in, FILE *fp_out)
Copy PGP output and look for signs of a good signature.
Definition: pgp.c:238
+ Here is the call graph for this function:

◆ pgp_class_encrypted_handler()

int pgp_class_encrypted_handler ( struct Body a,
struct State s 
)

Implements CryptModuleSpecs::encrypted_handler()

Definition at line 1193 of file pgp.c.

1194 {
1195  FILE *fp_in = NULL;
1196  struct Body *tattach = NULL;
1197  int rc = 0;
1198 
1199  FILE *fp_out = mutt_file_mkstemp();
1200  if (!fp_out)
1201  {
1202  mutt_perror(_("Can't create temporary file"));
1203  if (s->flags & MUTT_DISPLAY)
1204  {
1206  _("[-- Error: could not create temporary file --]\n"));
1207  }
1208  return -1;
1209  }
1210 
1211  if (s->flags & MUTT_DISPLAY)
1212  crypt_current_time(s, "PGP");
1213 
1214  tattach = pgp_decrypt_part(a, s, fp_out, a);
1215  if (tattach)
1216  {
1217  if (s->flags & MUTT_DISPLAY)
1218  {
1220  s, _("[-- The following data is PGP/MIME encrypted --]\n\n"));
1221  mutt_protected_headers_handler(tattach, s);
1222  }
1223 
1224  /* Store any protected headers in the parent so they can be
1225  * accessed for index updates after the handler recursion is done.
1226  * This is done before the handler to prevent a nested encrypted
1227  * handler from freeing the headers. */
1229  a->mime_headers = tattach->mime_headers;
1230  tattach->mime_headers = NULL;
1231 
1232  fp_in = s->fp_in;
1233  s->fp_in = fp_out;
1234  rc = mutt_body_handler(tattach, s);
1235  s->fp_in = fp_in;
1236 
1237  /* Embedded multipart signed protected headers override the
1238  * encrypted headers. We need to do this after the handler so
1239  * they can be printed in the pager. */
1240  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
1241  {
1243  a->mime_headers = tattach->parts->mime_headers;
1244  tattach->parts->mime_headers = NULL;
1245  }
1246 
1247  /* if a multipart/signed is the _only_ sub-part of a
1248  * multipart/encrypted, cache signature verification
1249  * status. */
1250  if (mutt_is_multipart_signed(tattach) && !tattach->next)
1251  a->goodsig |= tattach->goodsig;
1252 
1253  if (s->flags & MUTT_DISPLAY)
1254  {
1255  state_puts(s, "\n");
1256  state_attach_puts(s, _("[-- End of PGP/MIME encrypted data --]\n"));
1257  }
1258 
1259  mutt_body_free(&tattach);
1260  /* clear 'Invoking...' message, since there's no error */
1261  mutt_message(_("PGP message successfully decrypted"));
1262  }
1263  else
1264  {
1265  mutt_error(_("Could not decrypt PGP message"));
1266  /* void the passphrase, even if it's not necessarily the problem */
1268  rc = -1;
1269  }
1270 
1271  mutt_file_fclose(&fp_out);
1272 
1273  return rc;
1274 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1087
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define state_puts(STATE, STR)
Definition: state.h:55
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:83
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: pgp.c:75
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:71
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:407
bool goodsig
Good cryptographic signature.
Definition: body.h:75
static struct Body * pgp_decrypt_part(struct Body *a, struct State *s, FILE *fp_out, struct Body *p)
Decrypt part of a PGP message.
Definition: pgp.c:984
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define mutt_file_mkstemp()
Definition: file.h:106
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
#define mutt_error(...)
Definition: logging.h:84
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
+ Here is the call graph for this function:

◆ pgp_class_extract_key_from_attachment()

void pgp_class_extract_key_from_attachment ( FILE *  fp,
struct Body top 
)

Implements CryptModuleSpecs::pgp_extract_key_from_attachment()

Definition at line 961 of file pgp.c.

962 {
963  if (!fp)
964  {
965  mutt_error(_("Internal error. Please submit a bug report."));
966  return;
967  }
968 
969  mutt_endwin();
970 
971  OptDontHandlePgpKeys = true;
973  OptDontHandlePgpKeys = false;
974 }
#define _(a)
Definition: message.h:28
static void pgp_extract_keys_from_attachment(FILE *fp, struct Body *top)
Extract pgp keys from messages/attachments.
Definition: pgp.c:929
WHERE bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:36
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:

◆ pgp_class_void_passphrase()

void pgp_class_void_passphrase ( void  )

Implements CryptModuleSpecs::void_passphrase()

Definition at line 75 of file pgp.c.

76 {
77  memset(PgpPass, 0, sizeof(PgpPass));
78  PgpExptime = 0;
79 }
char PgpPass[1024]
Definition: pgp.c:69
time_t PgpExptime
Definition: pgp.c:70
+ Here is the caller graph for this function:

◆ pgp_class_valid_passphrase()

bool pgp_class_valid_passphrase ( void  )

Implements CryptModuleSpecs::valid_passphrase()

Definition at line 84 of file pgp.c.

85 {
86  if (pgp_use_gpg_agent())
87  {
88  *PgpPass = '\0';
89  return true; /* handled by gpg-agent */
90  }
91 
93  {
94  /* Use cached copy. */
95  return true;
96  }
97 
99 
100  if (mutt_get_password(_("Enter PGP passphrase:"), PgpPass, sizeof(PgpPass)) == 0)
101  {
103  return true;
104  }
105  else
106  PgpExptime = 0;
107 
108  return false;
109 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
#define mutt_get_password(msg, buf, buflen)
Definition: curs_lib.h:92
char PgpPass[1024]
Definition: pgp.c:69
#define _(a)
Definition: message.h:28
time_t mutt_date_add_timeout(time_t now, time_t timeout)
Safely add a timeout to a given time_t value.
Definition: date.c:625
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: pgp.c:75
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:117
long C_PgpTimeout
Config: Time in seconds to cache a passphrase.
Definition: config.c:74
time_t PgpExptime
Definition: pgp.c:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_class_verify_one()

int pgp_class_verify_one ( struct Body sigbdy,
struct State s,
const char *  tempfile 
)

Implements CryptModuleSpecs::verify_one()

Definition at line 860 of file pgp.c.

861 {
862  FILE *fp_pgp_out = NULL;
863  pid_t pid;
864  int badsig = -1;
865  struct Buffer *sigfile = mutt_buffer_pool_get();
866 
867  mutt_buffer_printf(sigfile, "%s.asc", tempfile);
868 
869  FILE *fp_sig = mutt_file_fopen(mutt_b2s(sigfile), "w");
870  if (!fp_sig)
871  {
872  mutt_perror(mutt_b2s(sigfile));
873  goto cleanup;
874  }
875 
876  fseeko(s->fp_in, sigbdy->offset, SEEK_SET);
877  mutt_file_copy_bytes(s->fp_in, fp_sig, sigbdy->length);
878  mutt_file_fclose(&fp_sig);
879 
880  FILE *fp_pgp_err = mutt_file_mkstemp();
881  if (!fp_pgp_err)
882  {
883  mutt_perror(_("Can't create temporary file"));
884  unlink(mutt_b2s(sigfile));
885  goto cleanup;
886  }
887 
888  crypt_current_time(s, "PGP");
889 
890  pid = pgp_invoke_verify(NULL, &fp_pgp_out, NULL, -1, -1, fileno(fp_pgp_err),
891  tempfile, mutt_b2s(sigfile));
892  if (pid != -1)
893  {
894  if (pgp_copy_checksig(fp_pgp_out, s->fp_out) >= 0)
895  badsig = 0;
896 
897  mutt_file_fclose(&fp_pgp_out);
898  fflush(fp_pgp_err);
899  rewind(fp_pgp_err);
900 
901  if (pgp_copy_checksig(fp_pgp_err, s->fp_out) >= 0)
902  badsig = 0;
903 
904  const int rv = filter_wait(pid);
905  if (rv)
906  badsig = -1;
907 
908  mutt_debug(LL_DEBUG1, "filter_wait returned %d\n", rv);
909  }
910 
911  mutt_file_fclose(&fp_pgp_err);
912 
913  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
914 
915  mutt_file_unlink(mutt_b2s(sigfile));
916 
917 cleanup:
918  mutt_buffer_pool_release(&sigfile);
919 
920  mutt_debug(LL_DEBUG1, "returning %d\n", badsig);
921  return badsig;
922 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
FILE * fp_in
File to read from.
Definition: state.h:46
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:71
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
pid_t pgp_invoke_verify(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname, const char *sig_fname)
Use PGP to verify a message.
Definition: pgpinvoke.c:270
#define mutt_b2s(buf)
Definition: buffer.h:41
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define mutt_file_mkstemp()
Definition: file.h:106
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:241
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
Log at debug level 1.
Definition: logging.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
static int pgp_copy_checksig(FILE *fp_in, FILE *fp_out)
Copy PGP output and look for signs of a good signature.
Definition: pgp.c:238
+ Here is the call graph for this function:

◆ pgp_class_traditional_encryptsign()

struct Body* pgp_class_traditional_encryptsign ( struct Body a,
SecurityFlags  flags,
char *  keylist 
)

Implements CryptModuleSpecs::pgp_traditional_encryptsign()

Definition at line 1668 of file pgp.c.

1669 {
1670  struct Body *b = NULL;
1671  char body_charset[256];
1672  char *from_charset = NULL;
1673  const char *send_charset = NULL;
1674  bool empty = false;
1675  bool err;
1676  char buf[256];
1677  pid_t pid;
1678  struct Buffer *pgpinfile = mutt_buffer_pool_get();
1679  struct Buffer *pgpoutfile = mutt_buffer_pool_get();
1680 
1681  if (a->type != TYPE_TEXT)
1682  goto cleanup;
1683  if (!mutt_istr_equal(a->subtype, "plain"))
1684  goto cleanup;
1685 
1686  FILE *fp_body = fopen(a->filename, "r");
1687  if (!fp_body)
1688  {
1689  mutt_perror(a->filename);
1690  goto cleanup;
1691  }
1692 
1693  mutt_buffer_mktemp(pgpinfile);
1694  FILE *fp_pgp_in = mutt_file_fopen(mutt_b2s(pgpinfile), "w");
1695  if (!fp_pgp_in)
1696  {
1697  mutt_perror(mutt_b2s(pgpinfile));
1698  mutt_file_fclose(&fp_body);
1699  goto cleanup;
1700  }
1701 
1702  /* The following code is really correct: If noconv is set,
1703  * a's charset parameter contains the on-disk character set, and
1704  * we have to convert from that to utf-8. If noconv is not set,
1705  * we have to convert from $charset to utf-8. */
1706 
1707  mutt_body_get_charset(a, body_charset, sizeof(body_charset));
1708  if (a->noconv)
1709  from_charset = body_charset;
1710  else
1711  from_charset = C_Charset;
1712 
1713  if (!mutt_ch_is_us_ascii(body_charset))
1714  {
1715  int c;
1716  struct FgetConv *fc = NULL;
1717 
1718  if (flags & SEC_ENCRYPT)
1719  send_charset = "us-ascii";
1720  else
1721  send_charset = "utf-8";
1722 
1723  /* fromcode is assumed to be correct: we set flags to 0 */
1724  fc = mutt_ch_fgetconv_open(fp_body, from_charset, "utf-8", 0);
1725  while ((c = mutt_ch_fgetconv(fc)) != EOF)
1726  fputc(c, fp_pgp_in);
1727 
1729  }
1730  else
1731  {
1732  send_charset = "us-ascii";
1733  mutt_file_copy_stream(fp_body, fp_pgp_in);
1734  }
1735  mutt_file_fclose(&fp_body);
1736  mutt_file_fclose(&fp_pgp_in);
1737 
1738  mutt_buffer_mktemp(pgpoutfile);
1739  FILE *fp_pgp_out = mutt_file_fopen(mutt_b2s(pgpoutfile), "w+");
1740  FILE *fp_pgp_err = mutt_file_mkstemp();
1741  if (!fp_pgp_out || !fp_pgp_err)
1742  {
1743  mutt_perror(fp_pgp_out ? "Can't create temporary file" : mutt_b2s(pgpoutfile));
1744  unlink(mutt_b2s(pgpinfile));
1745  if (fp_pgp_out)
1746  {
1747  mutt_file_fclose(&fp_pgp_out);
1748  unlink(mutt_b2s(pgpoutfile));
1749  }
1750  mutt_file_fclose(&fp_pgp_err);
1751  goto cleanup;
1752  }
1753 
1754  pid = pgp_invoke_traditional(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
1755  fileno(fp_pgp_err), mutt_b2s(pgpinfile), keylist, flags);
1756  if (pid == -1)
1757  {
1758  mutt_perror(_("Can't invoke PGP"));
1759  mutt_file_fclose(&fp_pgp_out);
1760  mutt_file_fclose(&fp_pgp_err);
1761  mutt_file_unlink(mutt_b2s(pgpinfile));
1762  unlink(mutt_b2s(pgpoutfile));
1763  goto cleanup;
1764  }
1765 
1766  if (pgp_use_gpg_agent())
1767  *PgpPass = '\0';
1768  if (flags & SEC_SIGN)
1769  fprintf(fp_pgp_in, "%s\n", PgpPass);
1770  mutt_file_fclose(&fp_pgp_in);
1771 
1772  if (filter_wait(pid) && C_PgpCheckExit)
1773  empty = true;
1774 
1775  mutt_file_unlink(mutt_b2s(pgpinfile));
1776 
1777  fflush(fp_pgp_out);
1778  fflush(fp_pgp_err);
1779 
1780  rewind(fp_pgp_out);
1781  rewind(fp_pgp_err);
1782 
1783  if (!empty)
1784  empty = (fgetc(fp_pgp_out) == EOF);
1785  mutt_file_fclose(&fp_pgp_out);
1786 
1787  err = false;
1788 
1789  while (fgets(buf, sizeof(buf), fp_pgp_err))
1790  {
1791  err = true;
1792  fputs(buf, stdout);
1793  }
1794 
1795  mutt_file_fclose(&fp_pgp_err);
1796 
1797  if (err)
1799 
1800  if (empty)
1801  {
1802  if (flags & SEC_SIGN)
1803  pgp_class_void_passphrase(); /* just in case */
1804  unlink(mutt_b2s(pgpoutfile));
1805  goto cleanup;
1806  }
1807 
1808  b = mutt_body_new();
1809 
1810  b->encoding = ENC_7BIT;
1811 
1812  b->type = TYPE_TEXT;
1813  b->subtype = mutt_str_dup("plain");
1814 
1815  mutt_param_set(&b->parameter, "x-action",
1816  (flags & SEC_ENCRYPT) ? "pgp-encrypted" : "pgp-signed");
1817  mutt_param_set(&b->parameter, "charset", send_charset);
1818 
1819  b->filename = mutt_buffer_strdup(pgpoutfile);
1820 
1821  b->disposition = DISP_NONE;
1822  b->unlink = true;
1823 
1824  b->noconv = true;
1825  b->use_disp = false;
1826 
1827  if (!(flags & SEC_ENCRYPT))
1828  b->encoding = a->encoding;
1829 
1830 cleanup:
1831  mutt_buffer_pool_release(&pgpinfile);
1832  mutt_buffer_pool_release(&pgpoutfile);
1833  return b;
1834 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file&#39;s character set.
Definition: charset.c:908
7-bit text
Definition: mime.h:49
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
char PgpPass[1024]
Definition: pgp.c:69
#define _(a)
Definition: message.h:28
pid_t pgp_invoke_traditional(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname, const char *uids, SecurityFlags flags)
Use PGP to create in inline-signed message.
Definition: pgpinvoke.c:372
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: pgp.c:75
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body&#39;s character set.
Definition: body.c:131
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:41
Type: &#39;text/*&#39;.
Definition: mime.h:38
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:117
#define mutt_file_mkstemp()
Definition: file.h:106
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
No preferred disposition.
Definition: mime.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
bool C_PgpCheckExit
Config: Check the exit code of PGP subprocess.
Definition: config.c:70
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, int flags)
Prepare a file for charset conversion.
Definition: charset.c:858
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:

◆ pgp_class_encrypt_message()

struct Body* pgp_class_encrypt_message ( struct Body a,
char *  keylist,
bool  sign,
const struct AddressList *  from 
)

Implements CryptModuleSpecs::pgp_encrypt_message()

Warning
"a" is no longer freed in this routine, you need to free it later. This is necessary for $fcc_attach.

Definition at line 1535 of file pgp.c.

1537 {
1538  char buf[1024];
1539  FILE *fp_pgp_in = NULL, *fp_tmp = NULL;
1540  struct Body *t = NULL;
1541  int err = 0;
1542  bool empty = false;
1543  pid_t pid;
1544  struct Buffer *tempfile = mutt_buffer_pool_get();
1545  struct Buffer *pgpinfile = mutt_buffer_pool_get();
1546 
1547  mutt_buffer_mktemp(tempfile);
1548  FILE *fp_out = mutt_file_fopen(mutt_b2s(tempfile), "w+");
1549  if (!fp_out)
1550  {
1551  mutt_perror(mutt_b2s(tempfile));
1552  goto cleanup;
1553  }
1554 
1555  FILE *fp_pgp_err = mutt_file_mkstemp();
1556  if (!fp_pgp_err)
1557  {
1558  mutt_perror(_("Can't create temporary file"));
1559  unlink(mutt_b2s(tempfile));
1560  mutt_file_fclose(&fp_out);
1561  goto cleanup;
1562  }
1563 
1564  mutt_buffer_mktemp(pgpinfile);
1565  fp_tmp = mutt_file_fopen(mutt_b2s(pgpinfile), "w");
1566  if (!fp_tmp)
1567  {
1568  mutt_perror(mutt_b2s(pgpinfile));
1569  unlink(mutt_b2s(tempfile));
1570  mutt_file_fclose(&fp_out);
1571  mutt_file_fclose(&fp_pgp_err);
1572  goto cleanup;
1573  }
1574 
1575  if (sign)
1577 
1578  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
1579  fputc('\n', fp_tmp);
1580  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
1581  mutt_file_fclose(&fp_tmp);
1582 
1583  pid = pgp_invoke_encrypt(&fp_pgp_in, NULL, NULL, -1, fileno(fp_out),
1584  fileno(fp_pgp_err), mutt_b2s(pgpinfile), keylist, sign);
1585  if (pid == -1)
1586  {
1587  mutt_file_fclose(&fp_out);
1588  mutt_file_fclose(&fp_pgp_err);
1589  unlink(mutt_b2s(pgpinfile));
1590  goto cleanup;
1591  }
1592 
1593  if (sign)
1594  {
1595  if (!pgp_use_gpg_agent())
1596  fputs(PgpPass, fp_pgp_in);
1597  fputc('\n', fp_pgp_in);
1598  }
1599  mutt_file_fclose(&fp_pgp_in);
1600 
1601  if (filter_wait(pid) && C_PgpCheckExit)
1602  empty = true;
1603 
1604  unlink(mutt_b2s(pgpinfile));
1605 
1606  fflush(fp_out);
1607  rewind(fp_out);
1608  if (!empty)
1609  empty = (fgetc(fp_out) == EOF);
1610  mutt_file_fclose(&fp_out);
1611 
1612  fflush(fp_pgp_err);
1613  rewind(fp_pgp_err);
1614  while (fgets(buf, sizeof(buf) - 1, fp_pgp_err))
1615  {
1616  err = 1;
1617  fputs(buf, stdout);
1618  }
1619  mutt_file_fclose(&fp_pgp_err);
1620 
1621  /* pause if there is any error output from PGP */
1622  if (err)
1624 
1625  if (empty)
1626  {
1627  /* fatal error while trying to encrypt message */
1628  if (sign)
1629  pgp_class_void_passphrase(); /* just in case */
1630  unlink(mutt_b2s(tempfile));
1631  goto cleanup;
1632  }
1633 
1634  t = mutt_body_new();
1635  t->type = TYPE_MULTIPART;
1636  t->subtype = mutt_str_dup("encrypted");
1637  t->encoding = ENC_7BIT;
1638  t->use_disp = false;
1639  t->disposition = DISP_INLINE;
1640 
1642  mutt_param_set(&t->parameter, "protocol", "application/pgp-encrypted");
1643 
1644  t->parts = mutt_body_new();
1645  t->parts->type = TYPE_APPLICATION;
1646  t->parts->subtype = mutt_str_dup("pgp-encrypted");
1647  t->parts->encoding = ENC_7BIT;
1648 
1649  t->parts->next = mutt_body_new();
1651  t->parts->next->subtype = mutt_str_dup("octet-stream");
1652  t->parts->next->encoding = ENC_7BIT;
1653  t->parts->next->filename = mutt_buffer_strdup(tempfile);
1654  t->parts->next->use_disp = true;
1656  t->parts->next->unlink = true; /* delete after sending the message */
1657  t->parts->next->d_filename = mutt_str_dup("msg.asc"); /* non pgp/mime can save */
1658 
1659 cleanup:
1660  mutt_buffer_pool_release(&tempfile);
1661  mutt_buffer_pool_release(&pgpinfile);
1662  return t;
1663 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:801
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
char PgpPass[1024]
Definition: pgp.c:69
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: pgp.c:75
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:85
Content is attached.
Definition: mime.h:63
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:41
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:117
#define mutt_file_mkstemp()
Definition: file.h:106
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
bool C_PgpCheckExit
Config: Check the exit code of PGP subprocess.
Definition: config.c:70
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
pid_t pgp_invoke_encrypt(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname, const char *uids, bool sign)
Use PGP to encrypt a file.
Definition: pgpinvoke.c:339
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:

◆ pgp_class_sign_message()

struct Body* pgp_class_sign_message ( struct Body a,
const struct AddressList *  from 
)

Implements CryptModuleSpecs::sign_message()

Definition at line 1283 of file pgp.c.

1284 {
1285  struct Body *t = NULL, *rv = NULL;
1286  char buf[1024];
1287  FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_err = NULL, *fp_signed = NULL;
1288  bool err = false;
1289  bool empty = true;
1290  pid_t pid;
1291  struct Buffer *sigfile = mutt_buffer_pool_get();
1292  struct Buffer *signedfile = mutt_buffer_pool_get();
1293 
1294  crypt_convert_to_7bit(a); /* Signed data _must_ be in 7-bit format. */
1295 
1296  mutt_buffer_mktemp(sigfile);
1297  FILE *fp_sig = mutt_file_fopen(mutt_b2s(sigfile), "w");
1298  if (!fp_sig)
1299  {
1300  goto cleanup;
1301  }
1302 
1303  mutt_buffer_mktemp(signedfile);
1304  fp_signed = mutt_file_fopen(mutt_b2s(signedfile), "w");
1305  if (!fp_signed)
1306  {
1307  mutt_perror(mutt_b2s(signedfile));
1308  mutt_file_fclose(&fp_sig);
1309  unlink(mutt_b2s(sigfile));
1310  goto cleanup;
1311  }
1312 
1313  mutt_write_mime_header(a, fp_signed, NeoMutt->sub);
1314  fputc('\n', fp_signed);
1315  mutt_write_mime_body(a, fp_signed, NeoMutt->sub);
1316  mutt_file_fclose(&fp_signed);
1317 
1318  pid = pgp_invoke_sign(&fp_pgp_in, &fp_pgp_out, &fp_pgp_err, -1, -1, -1,
1319  mutt_b2s(signedfile));
1320  if (pid == -1)
1321  {
1322  mutt_perror(_("Can't open PGP subprocess"));
1323  mutt_file_fclose(&fp_sig);
1324  unlink(mutt_b2s(sigfile));
1325  unlink(mutt_b2s(signedfile));
1326  goto cleanup;
1327  }
1328 
1329  if (!pgp_use_gpg_agent())
1330  fputs(PgpPass, fp_pgp_in);
1331  fputc('\n', fp_pgp_in);
1332  mutt_file_fclose(&fp_pgp_in);
1333 
1334  /* Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as
1335  * recommended for future releases of PGP. */
1336  while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1337  {
1338  if (mutt_str_equal("-----BEGIN PGP MESSAGE-----\n", buf))
1339  fputs("-----BEGIN PGP SIGNATURE-----\n", fp_sig);
1340  else if (mutt_str_equal("-----END PGP MESSAGE-----\n", buf))
1341  fputs("-----END PGP SIGNATURE-----\n", fp_sig);
1342  else
1343  fputs(buf, fp_sig);
1344  empty = false; /* got some output, so we're ok */
1345  }
1346 
1347  /* check for errors from PGP */
1348  err = false;
1349  while (fgets(buf, sizeof(buf) - 1, fp_pgp_err))
1350  {
1351  err = true;
1352  fputs(buf, stdout);
1353  }
1354 
1355  if (filter_wait(pid) && C_PgpCheckExit)
1356  empty = true;
1357 
1358  mutt_file_fclose(&fp_pgp_err);
1359  mutt_file_fclose(&fp_pgp_out);
1360  unlink(mutt_b2s(signedfile));
1361 
1362  if (mutt_file_fclose(&fp_sig) != 0)
1363  {
1364  mutt_perror("fclose");
1365  unlink(mutt_b2s(sigfile));
1366  goto cleanup;
1367  }
1368 
1369  if (err)
1371  if (empty)
1372  {
1373  unlink(mutt_b2s(sigfile));
1374  /* most likely error is a bad passphrase, so automatically forget it */
1376  goto cleanup; /* fatal error while signing */
1377  }
1378 
1379  t = mutt_body_new();
1380  t->type = TYPE_MULTIPART;
1381  t->subtype = mutt_str_dup("signed");
1382  t->encoding = ENC_7BIT;
1383  t->use_disp = false;
1384  t->disposition = DISP_INLINE;
1385  rv = t;
1386 
1388  mutt_param_set(&t->parameter, "protocol", "application/pgp-signature");
1389  mutt_param_set(&t->parameter, "micalg", pgp_micalg(mutt_b2s(sigfile)));
1390 
1391  t->parts = a;
1392 
1393  t->parts->next = mutt_body_new();
1394  t = t->parts->next;
1395  t->type = TYPE_APPLICATION;
1396  t->subtype = mutt_str_dup("pgp-signature");
1397  t->filename = mutt_buffer_strdup(sigfile);
1398  t->use_disp = false;
1399  t->disposition = DISP_NONE;
1400  t->encoding = ENC_7BIT;
1401  t->unlink = true; /* ok to remove this file after sending. */
1402  mutt_param_set(&t->parameter, "name", "signature.asc");
1403 
1404 cleanup:
1405  mutt_buffer_pool_release(&sigfile);
1406  mutt_buffer_pool_release(&signedfile);
1407  return rv;
1408 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
7-bit text
Definition: mime.h:49
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:801
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
char PgpPass[1024]
Definition: pgp.c:69
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase()
Definition: pgp.c:75
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:85
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:41
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:117
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
No preferred disposition.
Definition: mime.h:65
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
bool C_PgpCheckExit
Config: Check the exit code of PGP subprocess.
Definition: config.c:70
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
pid_t pgp_invoke_sign(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname)
Use PGP to sign a file.
Definition: pgpinvoke.c:315
const char * pgp_micalg(const char *fname)
Find the hash algorithm of a file.
Definition: pgpmicalg.c:229
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
+ Here is the call graph for this function:

◆ pgp_class_send_menu()

int pgp_class_send_menu ( struct Email e)

Implements CryptModuleSpecs::send_menu()

Definition at line 1839 of file pgp.c.

1840 {
1841  struct PgpKeyInfo *p = NULL;
1842  const char *prompt = NULL;
1843  const char *letters = NULL;
1844  const char *choices = NULL;
1845  char promptbuf[1024];
1846  int choice;
1847 
1848  if (!(WithCrypto & APPLICATION_PGP))
1849  return e->security;
1850 
1851  /* If autoinline and no crypto options set, then set inline. */
1852  if (C_PgpAutoinline &&
1853  !((e->security & APPLICATION_PGP) && (e->security & (SEC_SIGN | SEC_ENCRYPT))))
1854  {
1855  e->security |= SEC_INLINE;
1856  }
1857 
1858  e->security |= APPLICATION_PGP;
1859 
1860  char *mime_inline = NULL;
1861  if (e->security & SEC_INLINE)
1862  {
1863  /* L10N: The next string MUST have the same highlighted letter
1864  One of them will appear in each of the three strings marked "(inline"), below. */
1865  mime_inline = _("PGP/M(i)ME");
1866  }
1867  else
1868  {
1869  /* L10N: The previous string MUST have the same highlighted letter
1870  One of them will appear in each of the three strings marked "(inline"), below. */
1871  mime_inline = _("(i)nline");
1872  }
1873  /* Opportunistic encrypt is controlling encryption. Allow to toggle
1874  * between inline and mime, but not turn encryption on or off.
1875  * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different
1876  * letter choices for those. */
1878  {
1879  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
1880  {
1881  snprintf(promptbuf, sizeof(promptbuf),
1882  /* L10N: PGP options (inline) (opportunistic encryption is on) */
1883  _("PGP (s)ign, sign (a)s, %s format, (c)lear, or (o)ppenc mode "
1884  "off?"),
1885  mime_inline);
1886  prompt = promptbuf;
1887  /* L10N: PGP options (inline) (opportunistic encryption is on)
1888  The 'i' is from the "PGP/M(i)ME" or "(i)nline", above. */
1889  letters = _("saico");
1890  choices = "SaiCo";
1891  }
1892  else
1893  {
1894  /* L10N: PGP options (opportunistic encryption is on) */
1895  prompt = _("PGP (s)ign, sign (a)s, (c)lear, or (o)ppenc mode off?");
1896  /* L10N: PGP options (opportunistic encryption is on) */
1897  letters = _("saco");
1898  choices = "SaCo";
1899  }
1900  }
1901  /* Opportunistic encryption option is set, but is toggled off
1902  * for this message. */
1903  else if (C_CryptOpportunisticEncrypt)
1904  {
1905  /* When the message is not selected for signing or encryption, the toggle
1906  * between PGP/MIME and Traditional doesn't make sense. */
1907  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
1908  {
1909  snprintf(promptbuf, sizeof(promptbuf),
1910  /* L10N: PGP options (inline) (opportunistic encryption is off) */
1911  _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, "
1912  "(c)lear, or (o)ppenc mode?"),
1913  mime_inline);
1914  prompt = promptbuf;
1915  /* L10N: PGP options (inline) (opportunistic encryption is off)
1916  The 'i' is from the "PGP/M(i)ME" or "(i)nline", above. */
1917  letters = _("esabico");
1918  choices = "esabicO";
1919  }
1920  else
1921  {
1922  /* L10N: PGP options (opportunistic encryption is off) */
1923  prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (c)lear, or "
1924  "(o)ppenc mode?");
1925  /* L10N: PGP options (opportunistic encryption is off) */
1926  letters = _("esabco");
1927  choices = "esabcO";
1928  }
1929  }
1930  /* Opportunistic encryption is unset */
1931  else
1932  {
1933  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
1934  {
1935  snprintf(promptbuf, sizeof(promptbuf),
1936  /* L10N: PGP options (inline) */
1937  _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, or "
1938  "(c)lear?"),
1939  mime_inline);
1940  prompt = promptbuf;
1941  /* L10N: PGP options (inline)
1942  The 'i' is from the "PGP/M(i)ME" or "(i)nline", above. */
1943  letters = _("esabic");
1944  choices = "esabic";
1945  }
1946  else
1947  {
1948  /* L10N: PGP options */
1949  prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, or (c)lear?");
1950  /* L10N: PGP options */
1951  letters = _("esabc");
1952  choices = "esabc";
1953  }
1954  }
1955 
1956  choice = mutt_multi_choice(prompt, letters);
1957  if (choice > 0)
1958  {
1959  switch (choices[choice - 1])
1960  {
1961  case 'a': /* sign (a)s */
1962  OptPgpCheckTrust = false;
1963 
1964  p = pgp_ask_for_key(_("Sign as: "), NULL, KEYFLAG_NO_FLAGS, PGP_SECRING);
1965  if (p)
1966  {
1967  char input_signas[128];
1968  snprintf(input_signas, sizeof(input_signas), "0x%s", pgp_fpr_or_lkeyid(p));
1969  mutt_str_replace(&C_PgpSignAs, input_signas);
1970  pgp_key_free(&p);
1971 
1972  e->security |= SEC_SIGN;
1973 
1974  crypt_pgp_void_passphrase(); /* probably need a different passphrase */
1975  }
1976  break;
1977 
1978  case 'b': /* (b)oth */
1979  e->security |= (SEC_ENCRYPT | SEC_SIGN);
1980  break;
1981 
1982  case 'C':
1983  e->security &= ~SEC_SIGN;
1984  break;
1985 
1986  case 'c': /* (c)lear */
1987  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
1988  break;
1989 
1990  case 'e': /* (e)ncrypt */
1991  e->security |= SEC_ENCRYPT;
1992  e->security &= ~SEC_SIGN;
1993  break;
1994 
1995  case 'i': /* toggle (i)nline */
1996  e->security ^= SEC_INLINE;
1997  break;
1998 
1999  case 'O': /* oppenc mode on */
2000  e->security |= SEC_OPPENCRYPT;
2002  break;
2003 
2004  case 'o': /* oppenc mode off */
2005  e->security &= ~SEC_OPPENCRYPT;
2006  break;
2007 
2008  case 'S': /* (s)ign in oppenc mode */
2009  e->security |= SEC_SIGN;
2010  break;
2011 
2012  case 's': /* (s)ign */
2013  e->security &= ~SEC_ENCRYPT;
2014  e->security |= SEC_SIGN;
2015  break;
2016  }
2017  }
2018 
2019  return e->security;
2020 }
Secret keys.
Definition: pgpkey.h:40
#define WithCrypto
Definition: lib.h:123
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:187
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
#define _(a)
Definition: message.h:28
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:92
Information about a PGP key.
Definition: pgplib.h:46
bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: config.c:41
char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: config.c:52
void pgp_key_free(struct PgpKeyInfo **kpp)
Free a PGP key info.
Definition: pgplib.c:199
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:933
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition: lib.h:133
WHERE bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:49
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:93
char * pgp_fpr_or_lkeyid(struct PgpKeyInfo *k)
Get the fingerprint or long keyid.
Definition: pgp.c:221
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1021
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
bool C_PgpAutoinline
Config: Use old-style inline PGP messages (not recommended)
Definition: config.c:50
struct PgpKeyInfo * pgp_ask_for_key(char *tag, char *whatfor, KeyFlags abilities, enum PgpRing keyring)
Ask the user for a PGP key.
Definition: pgpkey.c:189
+ Here is the call graph for this function: