NeoMutt  2020-06-26-250-g349c94
Teaching an old dog new tricks
DOXYGEN
pgp.c File Reference

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

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "crypt.h"
#include "cryptglue.h"
#include "handler.h"
#include "hook.h"
#include "mutt_attach.h"
#include "muttlib.h"
#include "options.h"
#include "pgpinvoke.h"
#include "pgpkey.h"
#include "pgpmicalg.h"
#include "state.h"
#include "send/lib.h"
#include "pgp.h"
#include "pgplib.h"
+ Include dependency graph for pgp.c:

Go to the source code of this file.

Functions

void pgp_class_void_passphrase (void)
 Implements CryptModuleSpecs::void_passphrase() More...
 
bool pgp_class_valid_passphrase (void)
 Implements CryptModuleSpecs::valid_passphrase() More...
 
bool pgp_use_gpg_agent (void)
 Does the user want to use the gpg agent? More...
 
static struct PgpKeyInfokey_parent (struct PgpKeyInfo *k)
 Find a key's parent (if it's a subkey) More...
 
char * pgp_long_keyid (struct PgpKeyInfo *k)
 Get a key's long id. More...
 
char * pgp_short_keyid (struct PgpKeyInfo *k)
 Get a key's short id. 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...
 
static char * pgp_fingerprint (struct PgpKeyInfo *k)
 Get the key's fingerprint. More...
 
char * pgp_fpr_or_lkeyid (struct PgpKeyInfo *k)
 Get the fingerprint or long keyid. More...
 
static int pgp_copy_checksig (FILE *fp_in, FILE *fp_out)
 Copy PGP output and look for signs of a good signature. More...
 
static int pgp_check_pgp_decryption_okay_regex (FILE *fp_in)
 Check PGP output to look for successful outcome. More...
 
static int pgp_check_decryption_okay (FILE *fp_in)
 Check GPG output for status codes. More...
 
static void pgp_copy_clearsigned (FILE *fp_in, struct State *s, char *charset)
 Copy a clearsigned message, stripping the signature. More...
 
int pgp_class_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() More...
 
static int pgp_check_traditional_one_body (FILE *fp, struct Body *b)
 Check the body of an inline PGP message. More...
 
int pgp_class_check_traditional (FILE *fp, struct Body *b, bool just_one)
 Implements CryptModuleSpecs::pgp_check_traditional() More...
 
int pgp_class_verify_one (struct Body *sigbdy, struct State *s, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() More...
 
static void pgp_extract_keys_from_attachment (FILE *fp, struct Body *top)
 Extract pgp keys from messages/attachments. More...
 
void pgp_class_extract_key_from_attachment (FILE *fp, struct Body *top)
 Implements CryptModuleSpecs::pgp_extract_key_from_attachment() More...
 
static struct Bodypgp_decrypt_part (struct Body *a, struct State *s, FILE *fp_out, struct Body *p)
 Decrypt part of a PGP message. More...
 
int pgp_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() More...
 
int pgp_class_encrypted_handler (struct Body *a, struct State *s)
 Implements CryptModuleSpecs::encrypted_handler() More...
 
struct Bodypgp_class_sign_message (struct Body *a, const struct AddressList *from)
 Implements CryptModuleSpecs::sign_message() More...
 
char * pgp_class_find_keys (struct AddressList *addrlist, bool oppenc_mode)
 Implements CryptModuleSpecs::find_keys() 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_traditional_encryptsign (struct Body *a, SecurityFlags flags, char *keylist)
 Implements CryptModuleSpecs::pgp_traditional_encryptsign() More...
 
int pgp_class_send_menu (struct Email *e)
 Implements CryptModuleSpecs::send_menu() More...
 

Variables

char PgpPass [1024]
 
time_t PgpExptime = 0
 

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.c.

Function Documentation

◆ 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_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:

◆ key_parent()

static struct PgpKeyInfo* key_parent ( struct PgpKeyInfo k)
static

Find a key's parent (if it's a subkey)

Parameters
kPGP key
Return values
ptrParent key

Definition at line 140 of file pgp.c.

141 {
142  if ((k->flags & KEYFLAG_SUBKEY) && k->parent && C_PgpIgnoreSubkeys)
143  k = k->parent;
144 
145  return k;
146 }
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:141
KeyFlags flags
Definition: pgplib.h:51
struct PgpKeyInfo * parent
Definition: pgplib.h:56
bool C_PgpIgnoreSubkeys
Config: Only use the principal PGP key.
Definition: config.c:47
+ 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_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_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_fingerprint()

static char* pgp_fingerprint ( struct PgpKeyInfo k)
static

Get the key's fingerprint.

Parameters
kPGP key
Return values
ptrFingerprint string

Definition at line 203 of file pgp.c.

204 {
205  k = key_parent(k);
206 
207  return k->fingerprint;
208 }
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 * fingerprint
Definition: pgplib.h:49
+ 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 * 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_copy_checksig()

static int pgp_copy_checksig ( FILE *  fp_in,
FILE *  fp_out 
)
static

Copy PGP output and look for signs of a good signature.

Parameters
fp_inFile to read from
fp_outFile to write to
Return values
0Success
-1Error

Definition at line 238 of file pgp.c.

239 {
240  if (!fp_in || !fp_out)
241  return -1;
242 
243  int rc = -1;
244 
246  {
247  char *line = NULL;
248  size_t linelen;
249 
250  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, 0)))
251  {
252  if (mutt_regex_match(C_PgpGoodSign, line))
253  {
254  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
255  rc = 0;
256  }
257  else
258  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
259 
260  if (mutt_strn_equal(line, "[GNUPG:] ", 9))
261  continue;
262  fputs(line, fp_out);
263  fputc('\n', fp_out);
264  }
265  FREE(&line);
266  }
267  else
268  {
269  mutt_debug(LL_DEBUG2, "No pattern\n");
270  mutt_file_copy_stream(fp_in, fp_out);
271  rc = 1;
272  }
273 
274  return rc;
275 }
regex_t * regex
compiled expression
Definition: regex3.h:91
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
Log at debug level 2.
Definition: logging.h:41
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
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:609
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct Regex * C_PgpGoodSign
Config: Text indicating a good signature.
Definition: config.c:73
int const char int line
Definition: acutest.h:617
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_check_pgp_decryption_okay_regex()

static int pgp_check_pgp_decryption_okay_regex ( FILE *  fp_in)
static

Check PGP output to look for successful outcome.

Parameters
fp_inFile to read from
Return values
0Success
-1Error

Checks PGP output messages to look for the $pgp_decryption_okay message. This protects against messages with multipart/encrypted headers but which aren't actually encrypted.

Definition at line 287 of file pgp.c.

288 {
289  int rc = -1;
290 
292  {
293  char *line = NULL;
294  size_t linelen;
295 
296  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, 0)))
297  {
299  {
300  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
301  rc = 0;
302  break;
303  }
304  else
305  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
306  }
307  FREE(&line);
308  }
309  else
310  {
311  mutt_debug(LL_DEBUG2, "No pattern\n");
312  rc = 1;
313  }
314 
315  return rc;
316 }
regex_t * regex
compiled expression
Definition: regex3.h:91
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
Log at debug level 2.
Definition: logging.h:41
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:609
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int const char int line
Definition: acutest.h:617
struct Regex * C_PgpDecryptionOkay
Config: Text indicating a successful decryption.
Definition: config.c:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_check_decryption_okay()

static int pgp_check_decryption_okay ( FILE *  fp_in)
static

Check GPG output for status codes.

Parameters
fp_inFile to read from
Return values
1- no patterns were matched (if delegated to decryption_okay_regex)
0- DECRYPTION_OKAY was seen, with no PLAINTEXT outside
-1- No decryption status codes were encountered
-2- PLAINTEXT was encountered outside of DECRYPTION delimiters
-3- DECRYPTION_FAILED was encountered

Checks GnuPGP status fd output for various status codes indicating an issue. If $pgp_check_gpg_decrypt_status_fd is unset, it falls back to the old behavior of just scanning for $pgp_decryption_okay.

pgp_decrypt_part() should fail if the part is not encrypted, so we return less than 0 to indicate part or all was NOT actually encrypted.

On the other hand, for pgp_application_pgp_handler(), a "BEGIN PGP MESSAGE" could indicate a signed and armored message. For that we allow -1 and -2 as "valid" (with a warning).

Definition at line 338 of file pgp.c.

339 {
340  int rc = -1;
341  char *line = NULL, *s = NULL;
342  size_t linelen;
343  int inside_decrypt = 0;
344 
347 
348  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, 0)))
349  {
350  size_t plen = mutt_str_startswith(line, "[GNUPG:] ");
351  if (plen == 0)
352  continue;
353  s = line + plen;
354  mutt_debug(LL_DEBUG2, "checking \"%s\"\n", line);
355  if (mutt_str_startswith(s, "BEGIN_DECRYPTION"))
356  inside_decrypt = 1;
357  else if (mutt_str_startswith(s, "END_DECRYPTION"))
358  inside_decrypt = 0;
359  else if (mutt_str_startswith(s, "PLAINTEXT"))
360  {
361  if (!inside_decrypt)
362  {
364  "\tPLAINTEXT encountered outside of DECRYPTION\n");
365  rc = -2;
366  break;
367  }
368  }
369  else if (mutt_str_startswith(s, "DECRYPTION_FAILED"))
370  {
371  mutt_debug(LL_DEBUG2, "\tDECRYPTION_FAILED encountered. Failure\n");
372  rc = -3;
373  break;
374  }
375  else if (mutt_str_startswith(s, "DECRYPTION_OKAY"))
376  {
377  /* Don't break out because we still have to check for
378  * PLAINTEXT outside of the decryption boundaries. */
379  mutt_debug(LL_DEBUG2, "\tDECRYPTION_OKAY encountered\n");
380  rc = 0;
381  }
382  }
383  FREE(&line);
384 
385  return rc;
386 }
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
static int pgp_check_pgp_decryption_okay_regex(FILE *fp_in)
Check PGP output to look for successful outcome.
Definition: pgp.c:287
Log at debug level 2.
Definition: logging.h:41
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:165
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int const char int line
Definition: acutest.h:617
bool C_PgpCheckGpgDecryptStatusFd
Config: File descriptor used for status info.
Definition: config.c:71
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_copy_clearsigned()

static void pgp_copy_clearsigned ( FILE *  fp_in,
struct State s,
char *  charset 
)
static

Copy a clearsigned message, stripping the signature.

Parameters
fp_inFile to read from
sState to use
charsetCharset of file

XXX charset handling: We assume that it is safe to do character set decoding first, dash decoding second here, while we do it the other way around in the main handler.

(Note that we aren't worse than Outlook &c in this, and also note that we can successfully handle anything produced by any existing versions of neomutt.)

Definition at line 401 of file pgp.c.

402 {
403  char buf[8192];
404  bool complete, armor_header;
405 
406  rewind(fp_in);
407 
408  /* fromcode comes from the MIME Content-Type charset label. It might
409  * be a wrong label, so we want the ability to do corrections via
410  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
411  struct FgetConv *fc =
413 
414  for (complete = true, armor_header = true;
415  mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
416  {
417  if (!complete)
418  {
419  if (!armor_header)
420  state_puts(s, buf);
421  continue;
422  }
423 
424  if (mutt_str_equal(buf, "-----BEGIN PGP SIGNATURE-----\n"))
425  break;
426 
427  if (armor_header)
428  {
429  char *p = mutt_str_skip_whitespace(buf);
430  if (*p == '\0')
431  armor_header = false;
432  continue;
433  }
434 
435  if (s->prefix)
436  state_puts(s, s->prefix);
437 
438  if ((buf[0] == '-') && (buf[1] == ' '))
439  state_puts(s, buf + 2);
440  else
441  state_puts(s, buf);
442  }
443 
445 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:691
#define state_puts(STATE, STR)
Definition: state.h:55
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
char * p
Definition: charset.h:47
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:888
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file&#39;s charset into a string buffer.
Definition: charset.c:970
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
#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
Cursor for converting a file&#39;s encoding.
Definition: charset.h:41
+ Here is the call graph for this function:
+ Here is the caller 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:129
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_check_traditional_one_body()

static int pgp_check_traditional_one_body ( FILE *  fp,
struct Body b 
)
static

Check the body of an inline PGP message.

Parameters
fpFile to read
bBody to populate
Return values
1Success
0Error

Definition at line 766 of file pgp.c.

767 {
768  struct Buffer *tempfile = NULL;
769  char buf[8192];
770  int rc = 0;
771 
772  bool sgn = false;
773  bool enc = false;
774  bool key = false;
775 
776  if (b->type != TYPE_TEXT)
777  goto cleanup;
778 
779  tempfile = mutt_buffer_pool_get();
780  mutt_buffer_mktemp(tempfile);
781  if (mutt_decode_save_attachment(fp, b, mutt_b2s(tempfile), 0, MUTT_SAVE_NO_FLAGS) != 0)
782  {
783  unlink(mutt_b2s(tempfile));
784  goto cleanup;
785  }
786 
787  FILE *fp_tmp = fopen(mutt_b2s(tempfile), "r");
788  if (!fp_tmp)
789  {
790  unlink(mutt_b2s(tempfile));
791  goto cleanup;
792  }
793 
794  while (fgets(buf, sizeof(buf), fp_tmp))
795  {
796  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
797  if (plen != 0)
798  {
799  if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
800  enc = true;
801  else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
802  sgn = true;
803  else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
804  key = true;
805  }
806  }
807  mutt_file_fclose(&fp_tmp);
808  unlink(mutt_b2s(tempfile));
809 
810  if (!enc && !sgn && !key)
811  goto cleanup;
812 
813  /* fix the content type */
814 
815  mutt_param_set(&b->parameter, "format", "fixed");
816  if (enc)
817  mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
818  else if (sgn)
819  mutt_param_set(&b->parameter, "x-action", "pgp-signed");
820  else if (key)
821  mutt_param_set(&b->parameter, "x-action", "pgp-keys");
822 
823  rc = 1;
824 
825 cleanup:
826  mutt_buffer_pool_release(&tempfile);
827  return rc;
828 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
No flags set.
Definition: mutt_attach.h:55
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
String manipulation buffer.
Definition: buffer.h:33
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:165
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1000
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
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:
+ 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:550
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_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
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_extract_keys_from_attachment()

static void pgp_extract_keys_from_attachment ( FILE *  fp,
struct Body top 
)
static

Extract pgp keys from messages/attachments.

Parameters
fpFile to read from
topTop Attachment

Definition at line 929 of file pgp.c.

930 {
931  struct State s = { 0 };
932  struct Buffer *tempfname = mutt_buffer_pool_get();
933 
934  mutt_buffer_mktemp(tempfname);
935  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tempfname), "w");
936  if (!fp_tmp)
937  {
938  mutt_perror(mutt_b2s(tempfname));
939  goto cleanup;
940  }
941 
942  s.fp_in = fp;
943  s.fp_out = fp_tmp;
944 
945  mutt_body_handler(top, &s);
946 
947  mutt_file_fclose(&fp_tmp);
948 
949  pgp_class_invoke_import(mutt_b2s(tempfname));
951 
952  mutt_file_unlink(mutt_b2s(tempfname));
953 
954 cleanup:
955  mutt_buffer_pool_release(&tempfname);
956 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
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
FILE * fp_out
File to write to.
Definition: state.h:47
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 pgp_class_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import()
Definition: pgpinvoke.c:392
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:603
Keep track when processing files.
Definition: state.h:44
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ Here is the call graph for this function:
+ Here is the caller 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:570
#define mutt_error(...)
Definition: logging.h:84
+ Here is the call graph for this function:

◆ pgp_decrypt_part()

static struct Body* pgp_decrypt_part ( struct Body a,
struct State s,
FILE *  fp_out,
struct Body p 
)
static

Decrypt part of a PGP message.

Parameters
aBody of attachment
sState to use
fp_outFile to write to
pBody of parent (main email)
Return values
ptrNew Body for the attachment

Definition at line 984 of file pgp.c.

986 {
987  if (!a || !s || !fp_out || !p)
988  return NULL;
989 
990  char buf[1024];
991  FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_tmp = NULL;
992  struct stat info;
993  struct Body *tattach = NULL;
994  pid_t pid;
995  int rv;
996  struct Buffer *pgptmpfile = mutt_buffer_pool_get();
997 
998  FILE *fp_pgp_err = mutt_file_mkstemp();
999  if (!fp_pgp_err)
1000  {
1001  mutt_perror(_("Can't create temporary file"));
1002  goto cleanup;
1003  }
1004 
1005  mutt_buffer_mktemp(pgptmpfile);
1006  fp_pgp_tmp = mutt_file_fopen(mutt_b2s(pgptmpfile), "w");
1007  if (!fp_pgp_tmp)
1008  {
1009  mutt_perror(mutt_b2s(pgptmpfile));
1010  mutt_file_fclose(&fp_pgp_err);
1011  goto cleanup;
1012  }
1013 
1014  /* Position the stream at the beginning of the body, and send the data to
1015  * the temporary file. */
1016 
1017  fseeko(s->fp_in, a->offset, SEEK_SET);
1018  mutt_file_copy_bytes(s->fp_in, fp_pgp_tmp, a->length);
1019  mutt_file_fclose(&fp_pgp_tmp);
1020 
1021  pid = pgp_invoke_decrypt(&fp_pgp_in, &fp_pgp_out, NULL, -1, -1,
1022  fileno(fp_pgp_err), mutt_b2s(pgptmpfile));
1023  if (pid == -1)
1024  {
1025  mutt_file_fclose(&fp_pgp_err);
1026  unlink(mutt_b2s(pgptmpfile));
1027  if (s->flags & MUTT_DISPLAY)
1028  {
1030  s, _("[-- Error: could not create a PGP subprocess --]\n\n"));
1031  }
1032  goto cleanup;
1033  }
1034 
1035  /* send the PGP passphrase to the subprocess. Never do this if the agent is
1036  * active, because this might lead to a passphrase send as the message. */
1037  if (!pgp_use_gpg_agent())
1038  fputs(PgpPass, fp_pgp_in);
1039  fputc('\n', fp_pgp_in);
1040  mutt_file_fclose(&fp_pgp_in);
1041 
1042  /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
1043  * read_mime_header has a hard time parsing the message. */
1044  while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1045  {
1046  size_t len = mutt_str_len(buf);
1047  if ((len > 1) && (buf[len - 2] == '\r'))
1048  strcpy(buf + len - 2, "\n");
1049  fputs(buf, fp_out);
1050  }
1051 
1052  mutt_file_fclose(&fp_pgp_out);
1053  rv = filter_wait(pid);
1054  mutt_file_unlink(mutt_b2s(pgptmpfile));
1055 
1056  fflush(fp_pgp_err);
1057  rewind(fp_pgp_err);
1058  if (pgp_check_decryption_okay(fp_pgp_err) < 0)
1059  {
1060  mutt_error(_("Decryption failed"));
1062  mutt_file_fclose(&fp_pgp_err);
1063  goto cleanup;
1064  }
1065 
1066  if (s->flags & MUTT_DISPLAY)
1067  {
1068  rewind(fp_pgp_err);
1069  if ((pgp_copy_checksig(fp_pgp_err, s->fp_out) == 0) && !rv)
1070  p->goodsig = true;
1071  else
1072  p->goodsig = false;
1073  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
1074  }
1075  mutt_file_fclose(&fp_pgp_err);
1076 
1077  fflush(fp_out);
1078  rewind(fp_out);
1079 
1080  if (pgp_use_gpg_agent())
1082 
1083  if (fgetc(fp_out) == EOF)
1084  {
1085  mutt_error(_("Decryption failed"));
1087  goto cleanup;
1088  }
1089 
1090  rewind(fp_out);
1091 
1092  tattach = mutt_read_mime_header(fp_out, 0);
1093  if (tattach)
1094  {
1095  /* Need to set the length of this body part. */
1096  fstat(fileno(fp_out), &info);
1097  tattach->length = info.st_size - tattach->offset;
1098 
1099  /* See if we need to recurse on this MIME part. */
1100  mutt_parse_part(fp_out, tattach);
1101  }
1102 
1103 cleanup:
1104  mutt_buffer_pool_release(&pgptmpfile);
1105  return tattach;
1106 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
static int pgp_check_decryption_okay(FILE *fp_in)
Check GPG output for status codes.
Definition: pgp.c:338
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 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
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
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
pid_t pgp_invoke_decrypt(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 decrypt a file.
Definition: pgpinvoke.c:293
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
#define mutt_b2s(buf)
Definition: buffer.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:75
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
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
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
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1657
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
#define mutt_error(...)
Definition: logging.h:84
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
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:129
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1267
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:
+ 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:469
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:506
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_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:1085
#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:405
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_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:799
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:603
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_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:1461
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1345
#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:378
void mutt_crypt_hook(struct ListHead *list, struct Address *addr)
Find crypto hooks for an Address.
Definition: hook.c:745
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_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:799
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:603
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_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:603
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_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:932
#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 pgp_select_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:1019
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:

Variable Documentation

◆ PgpPass

char PgpPass[1024]

Definition at line 69 of file pgp.c.

◆ PgpExptime

time_t PgpExptime = 0

Definition at line 70 of file pgp.c.