NeoMutt  2021-10-29-43-g6b8931
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 117 of file pgp.c.

118 {
119  char *tty = NULL;
120 
121  /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
122  const bool c_pgp_use_gpg_agent =
123  cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
124  if (!c_pgp_use_gpg_agent)
125  return false;
126 
127  tty = ttyname(0);
128  if (tty)
129  {
130  setenv("GPG_TTY", tty, 0);
131  mutt_envlist_set("GPG_TTY", tty, false);
132  }
133 
134  return true;
135 }
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 142 of file pgp.c.

143 {
144  const bool c_pgp_ignore_subkeys =
145  cs_subset_bool(NeoMutt->sub, "pgp_ignore_subkeys");
146  if ((k->flags & KEYFLAG_SUBKEY) && k->parent && c_pgp_ignore_subkeys)
147  k = k->parent;
148 
149  return k;
150 }
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:131
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 157 of file pgp.c.

158 {
159  k = key_parent(k);
160 
161  return k->keyid;
162 }
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key's parent (if it's a subkey)
Definition: pgp.c:142
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 169 of file pgp.c.

170 {
171  k = key_parent(k);
172 
173  return k->keyid + 8;
174 }
+ 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 183 of file pgp.c.

184 {
185  const bool c_pgp_long_ids = cs_subset_bool(NeoMutt->sub, "pgp_long_ids");
186  if (c_pgp_long_ids)
187  return k->keyid;
188  return k->keyid + 8;
189 }
+ 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 196 of file pgp.c.

197 {
198  k = key_parent(k);
199 
200  return pgp_this_keyid(k);
201 }
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:183
+ 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 208 of file pgp.c.

209 {
210  k = key_parent(k);
211 
212  return k->fingerprint;
213 }
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 226 of file pgp.c.

227 {
228  char *fingerprint = pgp_fingerprint(k);
229  return fingerprint ? fingerprint : pgp_long_keyid(k);
230 }
static char * pgp_fingerprint(struct PgpKeyInfo *k)
Get the key's fingerprint.
Definition: pgp.c:208
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition: pgp.c:157
+ 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 243 of file pgp.c.

244 {
245  if (!fp_in || !fp_out)
246  return -1;
247 
248  int rc = -1;
249 
250  const struct Regex *c_pgp_good_sign =
251  cs_subset_regex(NeoMutt->sub, "pgp_good_sign");
252  if (c_pgp_good_sign && c_pgp_good_sign->regex)
253  {
254  char *line = NULL;
255  size_t linelen;
256 
257  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
258  {
259  if (mutt_regex_match(c_pgp_good_sign, line))
260  {
261  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
262  rc = 0;
263  }
264  else
265  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
266 
267  if (mutt_strn_equal(line, "[GNUPG:] ", 9))
268  continue;
269  fputs(line, fp_out);
270  fputc('\n', fp_out);
271  }
272  FREE(&line);
273  }
274  else
275  {
276  mutt_debug(LL_DEBUG2, "No pattern\n");
277  mutt_file_copy_stream(fp_in, fp_out);
278  rc = 1;
279  }
280 
281  return rc;
282 }
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
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:695
#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:627
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:404
Cached regular expression.
Definition: regex3.h:90
regex_t * regex
compiled expression
Definition: regex3.h:92
+ 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 294 of file pgp.c.

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

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

413 {
414  char buf[8192];
415  bool complete, armor_header;
416 
417  rewind(fp_in);
418 
419  /* fromcode comes from the MIME Content-Type charset label. It might
420  * be a wrong label, so we want the ability to do corrections via
421  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
422  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
423  struct FgetConv *fc =
424  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:899
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:869
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file's charset into a string buffer.
Definition: charset.c:981
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:715
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:530
#define state_puts(STATE, STR)
Definition: state.h:55
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:48
+ 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 785 of file pgp.c.

786 {
787  struct Buffer *tempfile = NULL;
788  char buf[8192];
789  bool rc = false;
790 
791  bool sgn = false;
792  bool enc = false;
793  bool key = false;
794 
795  if (b->type != TYPE_TEXT)
796  goto cleanup;
797 
798  tempfile = mutt_buffer_pool_get();
799  mutt_buffer_mktemp(tempfile);
800  if (mutt_decode_save_attachment(fp, b, mutt_buffer_string(tempfile), 0,
801  MUTT_SAVE_NO_FLAGS) != 0)
802  {
803  unlink(mutt_buffer_string(tempfile));
804  goto cleanup;
805  }
806 
807  FILE *fp_tmp = fopen(mutt_buffer_string(tempfile), "r");
808  if (!fp_tmp)
809  {
810  unlink(mutt_buffer_string(tempfile));
811  goto cleanup;
812  }
813 
814  while (fgets(buf, sizeof(buf), fp_tmp))
815  {
816  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
817  if (plen != 0)
818  {
819  if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
820  enc = true;
821  else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
822  sgn = true;
823  else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
824  key = true;
825  }
826  }
827  mutt_file_fclose(&fp_tmp);
828  unlink(mutt_buffer_string(tempfile));
829 
830  if (!enc && !sgn && !key)
831  goto cleanup;
832 
833  /* fix the content type */
834 
835  mutt_param_set(&b->parameter, "format", "fixed");
836  if (enc)
837  mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
838  else if (sgn)
839  mutt_param_set(&b->parameter, "x-action", "pgp-signed");
840  else if (key)
841  mutt_param_set(&b->parameter, "x-action", "pgp-keys");
842 
843  rc = true;
844 
845 cleanup:
846  mutt_buffer_pool_release(&tempfile);
847  return rc;
848 }
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:153
@ 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:1014
@ 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:61
unsigned int type
content-type primary type, ContentType
Definition: body.h:39
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 953 of file pgp.c.

954 {
955  struct State s = { 0 };
956  struct Buffer *tempfname = mutt_buffer_pool_get();
957 
958  mutt_buffer_mktemp(tempfname);
959  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfname), "w");
960  if (!fp_tmp)
961  {
962  mutt_perror(mutt_buffer_string(tempfname));
963  goto cleanup;
964  }
965 
966  s.fp_in = fp;
967  s.fp_out = fp_tmp;
968 
969  mutt_body_handler(top, &s);
970 
971  mutt_file_fclose(&fp_tmp);
972 
975 
977 
978 cleanup:
979  mutt_buffer_pool_release(&tempfname);
980 }
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:455
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
void pgp_class_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import() -.
Definition: pgpinvoke.c:416
#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:1600
Keep track when processing files.
Definition: state.h:45
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
+ 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 1008 of file pgp.c.

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

◆ PgpExptime

time_t PgpExptime = 0

Definition at line 68 of file pgp.c.