NeoMutt  2022-04-29-70-g0c028c
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 <time.h>
#include <unistd.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 "attach/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "crypt.h"
#include "cryptglue.h"
#include "handler.h"
#include "hook.h"
#include "muttlib.h"
#include "options.h"
#include "pgpinvoke.h"
#include "pgpkey.h"
#include "pgpmicalg.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 bool pgp_check_traditional_one_body (FILE *fp, struct Body *b)
 Check the body of an inline PGP message. More...
 
bool 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 (const 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...
 
SecurityFlags 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_use_gpg_agent()

bool pgp_use_gpg_agent ( void  )

Does the user want to use the gpg agent?

Return values
trueThe user wants to use the gpg agent
Note
This functions sets the environment variable $GPG_TTY

Definition at line 124 of file pgp.c.

125 {
126  char *tty = NULL;
127 
128  /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
129  const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
130  if (!c_pgp_use_gpg_agent)
131  return false;
132 
133  tty = ttyname(0);
134  if (tty)
135  {
136  setenv("GPG_TTY", tty, 0);
137  mutt_envlist_set("GPG_TTY", tty, false);
138  }
139 
140  return true;
141 }
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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 148 of file pgp.c.

149 {
150  const bool c_pgp_ignore_subkeys = cs_subset_bool(NeoMutt->sub, "pgp_ignore_subkeys");
151  if ((k->flags & KEYFLAG_SUBKEY) && k->parent && c_pgp_ignore_subkeys)
152  k = k->parent;
153 
154  return k;
155 }
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:134
KeyFlags flags
Definition: pgplib.h:51
struct PgpKeyInfo * parent
Definition: pgplib.h:56
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_long_keyid()

char* pgp_long_keyid ( struct PgpKeyInfo k)

Get a key's long id.

Parameters
kPGP key
Return values
ptrLong key id string

Definition at line 162 of file pgp.c.

163 {
164  k = key_parent(k);
165 
166  return k->keyid;
167 }
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key's parent (if it's a subkey)
Definition: pgp.c:148
char * keyid
Definition: pgplib.h:48
+ 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 174 of file pgp.c.

175 {
176  k = key_parent(k);
177 
178  return k->keyid + 8;
179 }
+ 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 188 of file pgp.c.

189 {
190  const bool c_pgp_long_ids = cs_subset_bool(NeoMutt->sub, "pgp_long_ids");
191  if (c_pgp_long_ids)
192  return k->keyid;
193  return k->keyid + 8;
194 }
+ Here is the call graph for this function:
+ 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 201 of file pgp.c.

202 {
203  k = key_parent(k);
204 
205  return pgp_this_keyid(k);
206 }
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:188
+ 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 213 of file pgp.c.

214 {
215  k = key_parent(k);
216 
217  return k->fingerprint;
218 }
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 231 of file pgp.c.

232 {
233  char *fingerprint = pgp_fingerprint(k);
234  return fingerprint ? fingerprint : pgp_long_keyid(k);
235 }
static char * pgp_fingerprint(struct PgpKeyInfo *k)
Get the key's fingerprint.
Definition: pgp.c:213
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition: pgp.c:162
+ 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 248 of file pgp.c.

249 {
250  if (!fp_in || !fp_out)
251  return -1;
252 
253  int rc = -1;
254 
255  const struct Regex *c_pgp_good_sign = cs_subset_regex(NeoMutt->sub, "pgp_good_sign");
256  if (c_pgp_good_sign && c_pgp_good_sign->regex)
257  {
258  char *line = NULL;
259  size_t linelen;
260 
261  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
262  {
263  if (mutt_regex_match(c_pgp_good_sign, line))
264  {
265  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
266  rc = 0;
267  }
268  else
269  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
270 
271  if (mutt_strn_equal(line, "[GNUPG:] ", 9))
272  continue;
273  fputs(line, fp_out);
274  fputc('\n', fp_out);
275  }
276  FREE(&line);
277  }
278  else
279  {
280  mutt_debug(LL_DEBUG2, "No pattern\n");
281  mutt_file_copy_stream(fp_in, fp_out);
282  rc = 1;
283  }
284 
285  return rc;
286 }
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
#define FREE(x)
Definition: memory.h:40
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:631
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:473
Cached regular expression.
Definition: regex3.h:89
regex_t * regex
compiled expression
Definition: regex3.h:91
+ 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 298 of file pgp.c.

299 {
300  int rc = -1;
301 
302  const struct Regex *c_pgp_decryption_okay = cs_subset_regex(NeoMutt->sub, "pgp_decryption_okay");
303  if (c_pgp_decryption_okay && c_pgp_decryption_okay->regex)
304  {
305  char *line = NULL;
306  size_t linelen;
307 
308  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
309  {
310  if (mutt_regex_match(c_pgp_decryption_okay, line))
311  {
312  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
313  rc = 0;
314  break;
315  }
316  else
317  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
318  }
319  FREE(&line);
320  }
321  else
322  {
323  mutt_debug(LL_DEBUG2, "No pattern\n");
324  rc = 1;
325  }
326 
327  return rc;
328 }
+ 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 350 of file pgp.c.

351 {
352  int rc = -1;
353  char *line = NULL, *s = NULL;
354  size_t linelen;
355  int inside_decrypt = 0;
356 
357  const bool c_pgp_check_gpg_decrypt_status_fd = cs_subset_bool(NeoMutt->sub, "pgp_check_gpg_decrypt_status_fd");
358  if (!c_pgp_check_gpg_decrypt_status_fd)
360 
361  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
362  {
363  size_t plen = mutt_str_startswith(line, "[GNUPG:] ");
364  if (plen == 0)
365  continue;
366  s = line + plen;
367  mutt_debug(LL_DEBUG2, "checking \"%s\"\n", line);
368  if (mutt_str_startswith(s, "BEGIN_DECRYPTION"))
369  inside_decrypt = 1;
370  else if (mutt_str_startswith(s, "END_DECRYPTION"))
371  inside_decrypt = 0;
372  else if (mutt_str_startswith(s, "PLAINTEXT"))
373  {
374  if (!inside_decrypt)
375  {
376  mutt_debug(LL_DEBUG2, " PLAINTEXT encountered outside of DECRYPTION\n");
377  rc = -2;
378  break;
379  }
380  }
381  else if (mutt_str_startswith(s, "DECRYPTION_FAILED"))
382  {
383  mutt_debug(LL_DEBUG2, " DECRYPTION_FAILED encountered. Failure\n");
384  rc = -3;
385  break;
386  }
387  else if (mutt_str_startswith(s, "DECRYPTION_OKAY"))
388  {
389  /* Don't break out because we still have to check for
390  * PLAINTEXT outside of the decryption boundaries. */
391  mutt_debug(LL_DEBUG2, " DECRYPTION_OKAY encountered\n");
392  rc = 0;
393  }
394  }
395  FREE(&line);
396 
397  return rc;
398 }
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
static int pgp_check_pgp_decryption_okay_regex(FILE *fp_in)
Check PGP output to look for successful outcome.
Definition: pgp.c:298
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
+ 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 413 of file pgp.c.

414 {
415  char buf[8192];
416  bool complete, armor_header;
417 
418  rewind(fp_in);
419 
420  /* fromcode comes from the MIME Content-Type charset label. It might
421  * be a wrong label, so we want the ability to do corrections via
422  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
423  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
424  struct FgetConv *fc = mutt_ch_fgetconv_open(fp_in, charset, c_charset, MUTT_ICONV_HOOK_FROM);
425 
426  for (complete = true, armor_header = true;
427  mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
428  {
429  if (!complete)
430  {
431  if (!armor_header)
432  state_puts(s, buf);
433  continue;
434  }
435 
436  if (mutt_str_equal(buf, "-----BEGIN PGP SIGNATURE-----\n"))
437  break;
438 
439  if (armor_header)
440  {
441  char *p = mutt_str_skip_whitespace(buf);
442  if (*p == '\0')
443  armor_header = false;
444  continue;
445  }
446 
447  if (s->prefix)
448  state_puts(s, s->prefix);
449 
450  if ((buf[0] == '-') && (buf[1] == ' '))
451  state_puts(s, buf + 2);
452  else
453  state_puts(s, buf);
454  }
455 
457 }
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:887
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, uint8_t flags)
Prepare a file for charset conversion.
Definition: charset.c:857
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file's charset into a string buffer.
Definition: charset.c:969
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
#define state_puts(STATE, STR)
Definition: state.h:56
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:784
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:599
Cursor for converting a file's encoding.
Definition: charset.h:41
char * p
Definition: charset.h:46
char * prefix
String to add to the beginning of each output line.
Definition: state.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_check_traditional_one_body()

static bool 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
trueSuccess
falseError

Definition at line 782 of file pgp.c.

783 {
784  struct Buffer *tempfile = NULL;
785  char buf[8192];
786  bool rc = false;
787 
788  bool sgn = false;
789  bool enc = false;
790  bool key = false;
791 
792  if (b->type != TYPE_TEXT)
793  goto cleanup;
794 
795  tempfile = mutt_buffer_pool_get();
796  mutt_buffer_mktemp(tempfile);
797  if (mutt_decode_save_attachment(fp, b, mutt_buffer_string(tempfile), 0,
798  MUTT_SAVE_NO_FLAGS) != 0)
799  {
800  unlink(mutt_buffer_string(tempfile));
801  goto cleanup;
802  }
803 
804  FILE *fp_tmp = fopen(mutt_buffer_string(tempfile), "r");
805  if (!fp_tmp)
806  {
807  unlink(mutt_buffer_string(tempfile));
808  goto cleanup;
809  }
810 
811  while (fgets(buf, sizeof(buf), fp_tmp))
812  {
813  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
814  if (plen != 0)
815  {
816  if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
817  enc = true;
818  else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
819  sgn = true;
820  else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
821  key = true;
822  }
823  }
824  mutt_file_fclose(&fp_tmp);
825  unlink(mutt_buffer_string(tempfile));
826 
827  if (!enc && !sgn && !key)
828  goto cleanup;
829 
830  /* fix the content type */
831 
832  mutt_param_set(&b->parameter, "format", "fixed");
833  if (enc)
834  mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
835  else if (sgn)
836  mutt_param_set(&b->parameter, "x-action", "pgp-signed");
837  else if (key)
838  mutt_param_set(&b->parameter, "x-action", "pgp-keys");
839 
840  rc = true;
841 
842 cleanup:
843  mutt_buffer_pool_release(&tempfile);
844  return rc;
845 }
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
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:1031
@ MUTT_SAVE_NO_FLAGS
No flags set.
Definition: mutt_attach.h:57
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller 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 950 of file pgp.c.

951 {
952  struct State s = { 0 };
953  struct Buffer *tempfname = mutt_buffer_pool_get();
954 
955  mutt_buffer_mktemp(tempfname);
956  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfname), "w");
957  if (!fp_tmp)
958  {
959  mutt_perror(mutt_buffer_string(tempfname));
960  goto cleanup;
961  }
962 
963  s.fp_in = fp;
964  s.fp_out = fp_tmp;
965 
966  mutt_body_handler(top, &s);
967 
968  mutt_file_fclose(&fp_tmp);
969 
972 
974 
975 cleanup:
976  mutt_buffer_pool_release(&tempfname);
977 }
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:498
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
void pgp_class_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import() -.
Definition: pgpinvoke.c:408
#define mutt_perror(...)
Definition: logging.h:88
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
Keep track when processing files.
Definition: state.h:46
FILE * fp_out
File to write to.
Definition: state.h:48
FILE * fp_in
File to read from.
Definition: state.h:47
+ Here is the call graph for this function:
+ Here is the caller 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 1005 of file pgp.c.

1007 {
1008  if (!a || !s || !fp_out || !p)
1009  return NULL;
1010 
1011  char buf[1024];
1012  FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_tmp = NULL;
1013  struct Body *tattach = NULL;
1014  pid_t pid;
1015  int rv;
1016  struct Buffer *pgptmpfile = mutt_buffer_pool_get();
1017 
1018  FILE *fp_pgp_err = mutt_file_mkstemp();
1019  if (!fp_pgp_err)
1020  {
1021  mutt_perror(_("Can't create temporary file"));
1022  goto cleanup;
1023  }
1024 
1025  mutt_buffer_mktemp(pgptmpfile);
1026  fp_pgp_tmp = mutt_file_fopen(mutt_buffer_string(pgptmpfile), "w");
1027  if (!fp_pgp_tmp)
1028  {
1029  mutt_perror(mutt_buffer_string(pgptmpfile));
1030  mutt_file_fclose(&fp_pgp_err);
1031  goto cleanup;
1032  }
1033 
1034  /* Position the stream at the beginning of the body, and send the data to
1035  * the temporary file. */
1036 
1037  if (!mutt_file_seek(s->fp_in, a->offset, SEEK_SET))
1038  {
1039  mutt_file_fclose(&fp_pgp_tmp);
1040  mutt_file_fclose(&fp_pgp_err);
1041  goto cleanup;
1042  }
1043  mutt_file_copy_bytes(s->fp_in, fp_pgp_tmp, a->length);
1044  mutt_file_fclose(&fp_pgp_tmp);
1045 
1046  pid = pgp_invoke_decrypt(&fp_pgp_in, &fp_pgp_out, NULL, -1, -1,
1047  fileno(fp_pgp_err), mutt_buffer_string(pgptmpfile));
1048  if (pid == -1)
1049  {
1050  mutt_file_fclose(&fp_pgp_err);
1051  unlink(mutt_buffer_string(pgptmpfile));
1052  if (s->flags & MUTT_DISPLAY)
1053  {
1054  state_attach_puts(s, _("[-- Error: could not create a PGP subprocess --]\n\n"));
1055  }
1056  goto cleanup;
1057  }
1058 
1059  /* send the PGP passphrase to the subprocess. Never do this if the agent is
1060  * active, because this might lead to a passphrase send as the message. */
1061  if (!pgp_use_gpg_agent())
1062  fputs(PgpPass, fp_pgp_in);
1063  fputc('\n', fp_pgp_in);
1064  mutt_file_fclose(&fp_pgp_in);
1065 
1066  /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
1067  * read_mime_header has a hard time parsing the message. */
1068  while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1069  {
1070  size_t len = mutt_str_len(buf);
1071  if ((len > 1) && (buf[len - 2] == '\r'))
1072  strcpy(buf + len - 2, "\n");
1073  fputs(buf, fp_out);
1074  }
1075 
1076  mutt_file_fclose(&fp_pgp_out);
1077 
1078  rv = filter_wait(pid);
1079  const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
1080  if (c_pgp_use_gpg_agent)
1082 
1083  mutt_file_unlink(mutt_buffer_string(pgptmpfile));
1084 
1085  fflush(fp_pgp_err);
1086  rewind(fp_pgp_err);
1087  if (pgp_check_decryption_okay(fp_pgp_err) < 0)
1088  {
1089  mutt_error(_("Decryption failed"));
1091  mutt_file_fclose(&fp_pgp_err);
1092  goto cleanup;
1093  }
1094 
1095  if (s->flags & MUTT_DISPLAY)
1096  {
1097  rewind(fp_pgp_err);
1098  if ((pgp_copy_checksig(fp_pgp_err, s->fp_out) == 0) && !rv)
1099  p->goodsig = true;
1100  else
1101  p->goodsig = false;
1102  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
1103  }
1104  mutt_file_fclose(&fp_pgp_err);
1105 
1106  fflush(fp_out);
1107  rewind(fp_out);
1108 
1109  if (fgetc(fp_out) == EOF)
1110  {
1111  mutt_error(_("Decryption failed"));
1113  goto cleanup;
1114  }
1115 
1116  rewind(fp_out);
1117  const long size = mutt_file_get_size_fp(fp_out);
1118  if (size == 0)
1119  {
1120  goto cleanup;
1121  }
1122 
1123  tattach = mutt_read_mime_header(fp_out, 0);
1124  if (tattach)
1125  {
1126  /* Need to set the length of this body part. */
1127  tattach->length = size - tattach->offset;
1128 
1129  /* See if we need to recurse on this MIME part. */
1130  mutt_parse_part(fp_out, tattach);
1131  }
1132 
1133 cleanup:
1134  mutt_buffer_pool_release(&pgptmpfile);
1135  return tattach;
1136 }
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:178
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:230
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1569
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define mutt_file_mkstemp()
Definition: file.h:112
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase() -.
Definition: pgp.c:74
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:100
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1737
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1318
char PgpPass[1024]
Definition: pgp.c:68
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:248
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:124
static int pgp_check_decryption_okay(FILE *fp_in)
Check GPG output for status codes.
Definition: pgp.c:350
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:302
The body of an email.
Definition: body.h:36
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
bool goodsig
Good cryptographic signature.
Definition: body.h:45
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ PgpPass

char PgpPass[1024]

Definition at line 68 of file pgp.c.

◆ PgpExptime

time_t PgpExptime = 0

Definition at line 69 of file pgp.c.