NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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/types.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 "editor/lib.h"
#include "history/lib.h"
#include "hooks/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "crypt.h"
#include "cryptglue.h"
#include "globals.h"
#include "module_data.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)
 Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
 
bool pgp_class_valid_passphrase (void)
 Ensure we have a valid passphrase - Implements CryptModuleSpecs::valid_passphrase() -.
 
bool pgp_use_gpg_agent (void)
 Does the user want to use the gpg agent?
 
static struct PgpKeyInfokey_parent (struct PgpKeyInfo *k)
 Find a key's parent (if it's a subkey)
 
char * pgp_long_keyid (struct PgpKeyInfo *k)
 Get a key's long id.
 
char * pgp_short_keyid (struct PgpKeyInfo *k)
 Get a key's short id.
 
char * pgp_this_keyid (struct PgpKeyInfo *k)
 Get the ID of this key.
 
char * pgp_keyid (struct PgpKeyInfo *k)
 Get the ID of the main (parent) key.
 
static char * pgp_fingerprint (struct PgpKeyInfo *k)
 Get the key's fingerprint.
 
char * pgp_fpr_or_lkeyid (struct PgpKeyInfo *k)
 Get the fingerprint or long keyid.
 
static int pgp_copy_checksig (FILE *fp_in, FILE *fp_out)
 Copy PGP output and look for signs of a good signature.
 
static int pgp_check_pgp_decryption_okay_regex (FILE *fp_in)
 Check PGP output to look for successful outcome.
 
static int pgp_check_decryption_okay (FILE *fp_in)
 Check GPG output for status codes.
 
static void pgp_copy_clearsigned (FILE *fp_in, struct State *state, char *charset)
 Copy a clearsigned message, stripping the signature.
 
int pgp_class_application_handler (struct Body *b, struct State *state)
 Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.
 
static bool pgp_check_traditional_one_body (FILE *fp, struct Body *b)
 Check the body of an inline PGP message.
 
bool pgp_class_check_traditional (FILE *fp, struct Body *b, bool just_one)
 Look for inline (non-MIME) PGP content - Implements CryptModuleSpecs::pgp_check_traditional() -.
 
int pgp_class_verify_one (struct Body *b, struct State *state, const char *tempfile)
 Check a signed MIME part against a signature - Implements CryptModuleSpecs::verify_one() -.
 
static void pgp_extract_keys_from_attachment (FILE *fp, struct Body *b)
 Extract pgp keys from messages/attachments.
 
void pgp_class_extract_key_from_attachment (FILE *fp, struct Body *b)
 Extract PGP key from an attachment - Implements CryptModuleSpecs::pgp_extract_key_from_attachment() -.
 
static struct Bodypgp_decrypt_part (struct Body *a, struct State *state, FILE *fp_out, struct Body *p)
 Decrypt part of a PGP message.
 
int pgp_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
 Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.
 
int pgp_class_encrypted_handler (struct Body *b, struct State *state)
 Manage a PGP or S/MIME encrypted MIME part - Implements CryptModuleSpecs::encrypted_handler() -.
 
struct Bodypgp_class_sign_message (struct Body *b, const struct AddressList *from)
 Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.
 
char * pgp_class_find_keys (const struct AddressList *addrlist, bool oppenc_mode)
 Find the keyids of the recipients of a message - Implements CryptModuleSpecs::find_keys() -.
 
struct Bodypgp_class_encrypt_message (struct Body *b, char *keylist, bool sign, const struct AddressList *from)
 PGP encrypt an email - Implements CryptModuleSpecs::pgp_encrypt_message() -.
 
struct Bodypgp_class_traditional_encryptsign (struct Body *b, SecurityFlags flags, char *keylist)
 Create an inline PGP encrypted, signed email - Implements CryptModuleSpecs::pgp_traditional_encryptsign() -.
 
SecurityFlags pgp_class_send_menu (struct Email *e)
 Ask the user whether to sign and/or encrypt the email - Implements CryptModuleSpecs::send_menu() -.
 

Detailed Description

PGP sign, encrypt, check routines.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Alejandro Colomar

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 envlist_set(&NeoMutt->env, "GPG_TTY", tty, false);
138 }
139
140 return true;
141}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
bool envlist_set(char ***envp, const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition envlist.c:88
Container for Accounts, Notifications.
Definition neomutt.h:41
char ** env
Private copy of the environment variables.
Definition neomutt.h:57
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ 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:143
KeyFlags flags
Key flags.
Definition pgplib.h:53
struct PgpKeyInfo * parent
Parent key.
Definition pgplib.h:58
+ 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
Key ID.
Definition pgplib.h:50
+ 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
Key fingerprint.
Definition pgplib.h:51
+ 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}
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition pgp.c:162
static char * pgp_fingerprint(struct PgpKeyInfo *k)
Get the key's fingerprint.
Definition pgp.c:213
+ 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 {
270 mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
271 }
272
273 if (mutt_strn_equal(line, "[GNUPG:] ", 9))
274 continue;
275 fputs(line, fp_out);
276 fputc('\n', fp_out);
277 }
278 FREE(&line);
279 }
280 else
281 {
282 mutt_debug(LL_DEBUG2, "No pattern\n");
283 mutt_file_copy_stream(fp_in, fp_out);
284 rc = 1;
285 }
286
287 return rc;
288}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition helpers.c:217
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
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:678
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition file.h:40
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition regex.c:614
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:429
Cached regular expression.
Definition regex3.h:85
regex_t * regex
compiled expression
Definition regex3.h:87
+ 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 300 of file pgp.c.

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

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

Copy a clearsigned message, stripping the signature.

Parameters
fp_inFile to read from
stateState 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 421 of file pgp.c.

422{
423 char buf[8192] = { 0 };
424 bool complete, armor_header;
425
426 rewind(fp_in);
427
428 /* fromcode comes from the MIME Content-Type charset label. It might
429 * be a wrong label, so we want the ability to do corrections via
430 * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
431 struct FgetConv *fc = mutt_ch_fgetconv_open(fp_in, charset, cc_charset(), MUTT_ICONV_HOOK_FROM);
432
433 for (complete = true, armor_header = true;
434 mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
435 {
436 if (!complete)
437 {
438 if (!armor_header)
439 state_puts(state, buf);
440 continue;
441 }
442
443 if (mutt_str_equal(buf, "-----BEGIN PGP SIGNATURE-----\n"))
444 break;
445
446 if (armor_header)
447 {
448 char *p = mutt_str_skip_whitespace(buf);
449 if (*p == '\0')
450 armor_header = false;
451 continue;
452 }
453
454 if (state->prefix)
455 state_puts(state, state->prefix);
456
457 if ((buf[0] == '-') && (buf[1] == ' '))
458 state_puts(state, buf + 2);
459 else
460 state_puts(state, buf);
461 }
462
464}
const char * cc_charset(void)
Get the cached value of $charset.
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:919
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file's charset into a string buffer.
Definition charset.c:1028
void mutt_ch_fgetconv_close(struct FgetConv **ptr)
Close an fgetconv handle.
Definition charset.c:948
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition charset.h:67
#define state_puts(STATE, STR)
Definition state.h:58
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition string.c:556
Cursor for converting a file's encoding.
Definition charset.h:45
char * p
Current position in output buffer.
Definition charset.h:50
const char * prefix
String to add to the beginning of each output line.
Definition state.h:51
+ 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 799 of file pgp.c.

800{
801 struct Buffer *tempfile = NULL;
802 char buf[8192] = { 0 };
803 bool rc = false;
804
805 bool sgn = false;
806 bool enc = false;
807 bool key = false;
808
809 if (b->type != TYPE_TEXT)
810 goto cleanup;
811
812 tempfile = buf_pool_get();
813 buf_mktemp(tempfile);
815 MUTT_SAVE_NO_FLAGS) != 0)
816 {
817 unlink(buf_string(tempfile));
818 goto cleanup;
819 }
820
821 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "r");
822 if (!fp_tmp)
823 {
824 unlink(buf_string(tempfile));
825 goto cleanup;
826 }
827
828 while (fgets(buf, sizeof(buf), fp_tmp))
829 {
830 size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
831 if (plen != 0)
832 {
833 if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
834 enc = true;
835 else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
836 sgn = true;
837 else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
838 key = true;
839 }
840 }
841 mutt_file_fclose(&fp_tmp);
842 unlink(buf_string(tempfile));
843
844 if (!enc && !sgn && !key)
845 goto cleanup;
846
847 /* fix the content type */
848
849 mutt_param_set(&b->parameter, "format", "fixed");
850 if (enc)
851 mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
852 else if (sgn)
853 mutt_param_set(&b->parameter, "x-action", "pgp-signed");
854 else if (key)
855 mutt_param_set(&b->parameter, "x-action", "pgp-keys");
856
857 rc = true;
858
859cleanup:
860 buf_pool_release(&tempfile);
861 return rc;
862}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
#define STATE_NO_FLAGS
No flags are set.
Definition state.h:32
int mutt_decode_save_attachment(FILE *fp, struct Body *b, const char *path, StateFlags flags, enum SaveAttach opt)
Decode, then save an attachment.
@ MUTT_SAVE_NO_FLAGS
Overwrite existing file (the default)
Definition mutt_attach.h:58
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition parameter.c:111
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
unsigned int type
content-type primary type, ContentType
Definition body.h:40
String manipulation buffer.
Definition buffer.h:36
#define buf_mktemp(buf)
Definition tmp.h:33
+ 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 * b )
static

Extract pgp keys from messages/attachments.

Parameters
fpFile to read from
bTop Attachment

Definition at line 969 of file pgp.c.

970{
971 struct State state = { 0 };
972 struct Buffer *tempfile = buf_pool_get();
973
974 buf_mktemp(tempfile);
975 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
976 if (!fp_tmp)
977 {
978 mutt_perror("%s", buf_string(tempfile));
979 goto cleanup;
980 }
981
982 state.fp_in = fp;
983 state.fp_out = fp_tmp;
984
985 mutt_body_handler(b, &state);
986
987 mutt_file_fclose(&fp_tmp);
988
991
992 mutt_file_unlink(buf_string(tempfile));
993
994cleanup:
995 buf_pool_release(&tempfile);
996}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:175
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
void pgp_class_invoke_import(const char *fname)
Import a key from a message into the user's public key ring - Implements CryptModuleSpecs::pgp_invoke...
Definition pgpinvoke.c:287
#define mutt_perror(...)
Definition logging2.h:95
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1664
Keep track when processing files.
Definition state.h:48
FILE * fp_out
File to write to.
Definition state.h:50
FILE * fp_in
File to read from.
Definition state.h:49
+ 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 * state,
FILE * fp_out,
struct Body * p )
static

Decrypt part of a PGP message.

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

Definition at line 1024 of file pgp.c.

1026{
1027 if (!a || !state || !fp_out || !p)
1028 return NULL;
1029
1031 char buf[1024] = { 0 };
1032 FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_tmp = NULL;
1033 struct Body *tattach = NULL;
1034 pid_t pid;
1035 int rv;
1036 struct Buffer *tempfile = buf_pool_get();
1037
1038 FILE *fp_pgp_err = mutt_file_mkstemp();
1039 if (!fp_pgp_err)
1040 {
1041 mutt_perror(_("Can't create temporary file"));
1042 goto cleanup;
1043 }
1044
1045 buf_mktemp(tempfile);
1046 fp_pgp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
1047 if (!fp_pgp_tmp)
1048 {
1049 mutt_perror("%s", buf_string(tempfile));
1050 mutt_file_fclose(&fp_pgp_err);
1051 goto cleanup;
1052 }
1053
1054 /* Position the stream at the beginning of the body, and send the data to
1055 * the temporary file. */
1056
1057 if (!mutt_file_seek(state->fp_in, a->offset, SEEK_SET))
1058 {
1059 mutt_file_fclose(&fp_pgp_tmp);
1060 mutt_file_fclose(&fp_pgp_err);
1061 goto cleanup;
1062 }
1063 mutt_file_copy_bytes(state->fp_in, fp_pgp_tmp, a->length);
1064 mutt_file_fclose(&fp_pgp_tmp);
1065
1066 pid = pgp_invoke_decrypt(&fp_pgp_in, &fp_pgp_out, NULL, -1, -1,
1067 fileno(fp_pgp_err), buf_string(tempfile));
1068 if (pid == -1)
1069 {
1070 mutt_file_fclose(&fp_pgp_err);
1071 unlink(buf_string(tempfile));
1072 if (state->flags & STATE_DISPLAY)
1073 {
1074 state_attach_puts(state, _("[-- Error: could not create a PGP subprocess --]\n\n"));
1075 }
1076 goto cleanup;
1077 }
1078
1079 /* send the PGP passphrase to the subprocess. Never do this if the agent is
1080 * active, because this might lead to a passphrase send as the message. */
1081 if (!pgp_use_gpg_agent())
1082 fputs(mod_data->pgp_pass, fp_pgp_in);
1083 fputc('\n', fp_pgp_in);
1084 mutt_file_fclose(&fp_pgp_in);
1085
1086 /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
1087 * read_mime_header has a hard time parsing the message. */
1088 while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1089 {
1090 size_t len = mutt_str_len(buf);
1091 if ((len > 1) && (buf[len - 2] == '\r'))
1092 strcpy(buf + len - 2, "\n");
1093 fputs(buf, fp_out);
1094 }
1095
1096 mutt_file_fclose(&fp_pgp_out);
1097
1098 rv = filter_wait(pid);
1099 const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
1100 if (c_pgp_use_gpg_agent)
1102
1103 mutt_file_unlink(buf_string(tempfile));
1104
1105 fflush(fp_pgp_err);
1106 rewind(fp_pgp_err);
1107 if (pgp_check_decryption_okay(fp_pgp_err) < 0)
1108 {
1109 mutt_error(_("Decryption failed"));
1111 mutt_file_fclose(&fp_pgp_err);
1112 goto cleanup;
1113 }
1114
1115 if (state->flags & STATE_DISPLAY)
1116 {
1117 rewind(fp_pgp_err);
1118 if ((pgp_copy_checksig(fp_pgp_err, state->fp_out) == 0) && !rv)
1119 p->goodsig = true;
1120 else
1121 p->goodsig = false;
1122 state_attach_puts(state, _("[-- End of PGP output --]\n\n"));
1123 }
1124 mutt_file_fclose(&fp_pgp_err);
1125
1126 fflush(fp_out);
1127 rewind(fp_out);
1128
1129 if (fgetc(fp_out) == EOF)
1130 {
1131 mutt_error(_("Decryption failed"));
1133 goto cleanup;
1134 }
1135
1136 rewind(fp_out);
1137 const long size = mutt_file_get_size_fp(fp_out);
1138 if (size == 0)
1139 {
1140 goto cleanup;
1141 }
1142
1143 tattach = mutt_read_mime_header(fp_out, 0);
1144 if (tattach)
1145 {
1146 /* Need to set the length of this body part. */
1147 tattach->length = size - tattach->offset;
1148
1149 /* See if we need to recurse on this MIME part. */
1150 mutt_parse_part(fp_out, tattach);
1151 }
1152
1153cleanup:
1154 buf_pool_release(&tempfile);
1155 return tattach;
1156}
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition curs_lib.c:102
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition parse.c:1794
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition parse.c:1331
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:192
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition file.c:1432
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
void pgp_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition pgp.c:71
#define mutt_error(...)
Definition logging2.h:94
@ MODULE_ID_NCRYPT
ModuleNcrypt, Ncrypt
Definition module_api.h:80
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:228
#define _(a)
Definition message.h:28
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition state.c:104
#define STATE_DISPLAY
Output is displayed to the user.
Definition state.h:33
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:665
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:354
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:181
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
Ncrypt private Module data.
Definition module_data.h:38
char pgp_pass[1024]
Cached PGP Passphrase.
Definition module_data.h:50
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:52
#define mutt_file_mkstemp()
Definition tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function: