NeoMutt  2024-02-01-25-ga71e95
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 <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 "editor/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "crypt.h"
#include "cryptglue.h"
#include "globals.h"
#include "handler.h"
#include "hook.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() -.
 

Variables

static char PgpPass [1024]
 Cached PGP Passphrase.
 
static time_t PgpExptime = 0
 Unix time when PgpPass expires.
 

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 127 of file pgp.c.

128{
129 char *tty = NULL;
130
131 /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
132 const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
133 if (!c_pgp_use_gpg_agent)
134 return false;
135
136 tty = ttyname(0);
137 if (tty)
138 {
139 setenv("GPG_TTY", tty, 0);
140 envlist_set(&EnvList, "GPG_TTY", tty, false);
141 }
142
143 return true;
144}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
bool envlist_set(char ***envp, const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:88
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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 151 of file pgp.c.

152{
153 const bool c_pgp_ignore_subkeys = cs_subset_bool(NeoMutt->sub, "pgp_ignore_subkeys");
154 if ((k->flags & KEYFLAG_SUBKEY) && k->parent && c_pgp_ignore_subkeys)
155 k = k->parent;
156
157 return k;
158}
#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 165 of file pgp.c.

166{
167 k = key_parent(k);
168
169 return k->keyid;
170}
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key's parent (if it's a subkey)
Definition: pgp.c:151
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 177 of file pgp.c.

178{
179 k = key_parent(k);
180
181 return k->keyid + 8;
182}
+ 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 191 of file pgp.c.

192{
193 const bool c_pgp_long_ids = cs_subset_bool(NeoMutt->sub, "pgp_long_ids");
194 if (c_pgp_long_ids)
195 return k->keyid;
196 return k->keyid + 8;
197}
+ 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 204 of file pgp.c.

205{
206 k = key_parent(k);
207
208 return pgp_this_keyid(k);
209}
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:191
+ 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 216 of file pgp.c.

217{
218 k = key_parent(k);
219
220 return k->fingerprint;
221}
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 234 of file pgp.c.

235{
236 char *fingerprint = pgp_fingerprint(k);
237 return fingerprint ? fingerprint : pgp_long_keyid(k);
238}
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition: pgp.c:165
static char * pgp_fingerprint(struct PgpKeyInfo *k)
Get the key's fingerprint.
Definition: pgp.c:216
+ 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 251 of file pgp.c.

252{
253 if (!fp_in || !fp_out)
254 return -1;
255
256 int rc = -1;
257
258 const struct Regex *c_pgp_good_sign = cs_subset_regex(NeoMutt->sub, "pgp_good_sign");
259 if (c_pgp_good_sign && c_pgp_good_sign->regex)
260 {
261 char *line = NULL;
262 size_t linelen;
263
264 while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
265 {
266 if (mutt_regex_match(c_pgp_good_sign, line))
267 {
268 mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
269 rc = 0;
270 }
271 else
272 {
273 mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
274 }
275
276 if (mutt_strn_equal(line, "[GNUPG:] ", 9))
277 continue;
278 fputs(line, fp_out);
279 fputc('\n', fp_out);
280 }
281 FREE(&line);
282 }
283 else
284 {
285 mutt_debug(LL_DEBUG2, "No pattern\n");
286 mutt_file_copy_stream(fp_in, fp_out);
287 rc = 1;
288 }
289
290 return rc;
291}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:218
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:282
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:801
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:40
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#define FREE(x)
Definition: memory.h:45
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:639
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:474
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 303 of file pgp.c.

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

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

425{
426 char buf[8192] = { 0 };
427 bool complete, armor_header;
428
429 rewind(fp_in);
430
431 /* fromcode comes from the MIME Content-Type charset label. It might
432 * be a wrong label, so we want the ability to do corrections via
433 * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
434 struct FgetConv *fc = mutt_ch_fgetconv_open(fp_in, charset, cc_charset(), MUTT_ICONV_HOOK_FROM);
435
436 for (complete = true, armor_header = true;
437 mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
438 {
439 if (!complete)
440 {
441 if (!armor_header)
442 state_puts(state, buf);
443 continue;
444 }
445
446 if (mutt_str_equal(buf, "-----BEGIN PGP SIGNATURE-----\n"))
447 break;
448
449 if (armor_header)
450 {
451 char *p = mutt_str_skip_whitespace(buf);
452 if (*p == '\0')
453 armor_header = false;
454 continue;
455 }
456
457 if (state->prefix)
458 state_puts(state, state->prefix);
459
460 if ((buf[0] == '-') && (buf[1] == ' '))
461 state_puts(state, buf + 2);
462 else
463 state_puts(state, buf);
464 }
465
467}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:116
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:932
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file's charset into a string buffer.
Definition: charset.c:1044
void mutt_ch_fgetconv_close(struct FgetConv **ptr)
Close an fgetconv handle.
Definition: charset.c:964
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:73
#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:709
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:600
Cursor for converting a file's encoding.
Definition: charset.h:42
char * p
Definition: charset.h:47
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 802 of file pgp.c.

803{
804 struct Buffer *tempfile = NULL;
805 char buf[8192] = { 0 };
806 bool rc = false;
807
808 bool sgn = false;
809 bool enc = false;
810 bool key = false;
811
812 if (b->type != TYPE_TEXT)
813 goto cleanup;
814
815 tempfile = buf_pool_get();
816 buf_mktemp(tempfile);
818 MUTT_SAVE_NO_FLAGS) != 0)
819 {
820 unlink(buf_string(tempfile));
821 goto cleanup;
822 }
823
824 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "r");
825 if (!fp_tmp)
826 {
827 unlink(buf_string(tempfile));
828 goto cleanup;
829 }
830
831 while (fgets(buf, sizeof(buf), fp_tmp))
832 {
833 size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
834 if (plen != 0)
835 {
836 if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
837 enc = true;
838 else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
839 sgn = true;
840 else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
841 key = true;
842 }
843 }
844 mutt_file_fclose(&fp_tmp);
845 unlink(buf_string(tempfile));
846
847 if (!enc && !sgn && !key)
848 goto cleanup;
849
850 /* fix the content type */
851
852 mutt_param_set(&b->parameter, "format", "fixed");
853 if (enc)
854 mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
855 else if (sgn)
856 mutt_param_set(&b->parameter, "x-action", "pgp-signed");
857 else if (key)
858 mutt_param_set(&b->parameter, "x-action", "pgp-keys");
859
860 rc = true;
861
862cleanup:
863 buf_pool_release(&tempfile);
864 return rc;
865}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
#define mutt_file_fclose(FP)
Definition: file.h:148
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
@ 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.
Definition: mutt_attach.c:1039
@ MUTT_SAVE_NO_FLAGS
No flags set.
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:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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: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 972 of file pgp.c.

973{
974 struct State state = { 0 };
975 struct Buffer *tempfname = buf_pool_get();
976
977 buf_mktemp(tempfname);
978 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfname), "w");
979 if (!fp_tmp)
980 {
981 mutt_perror("%s", buf_string(tempfname));
982 goto cleanup;
983 }
984
985 state.fp_in = fp;
986 state.fp_out = fp_tmp;
987
988 mutt_body_handler(b, &state);
989
990 mutt_file_fclose(&fp_tmp);
991
994
995 mutt_file_unlink(buf_string(tempfname));
996
997cleanup:
998 buf_pool_release(&tempfname);
999}
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:216
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:406
#define mutt_perror(...)
Definition: logging2.h:93
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1631
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 1027 of file pgp.c.

1029{
1030 if (!a || !state || !fp_out || !p)
1031 return NULL;
1032
1033 char buf[1024] = { 0 };
1034 FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_tmp = NULL;
1035 struct Body *tattach = NULL;
1036 pid_t pid;
1037 int rv;
1038 struct Buffer *pgptmpfile = buf_pool_get();
1039
1040 FILE *fp_pgp_err = mutt_file_mkstemp();
1041 if (!fp_pgp_err)
1042 {
1043 mutt_perror(_("Can't create temporary file"));
1044 goto cleanup;
1045 }
1046
1047 buf_mktemp(pgptmpfile);
1048 fp_pgp_tmp = mutt_file_fopen(buf_string(pgptmpfile), "w");
1049 if (!fp_pgp_tmp)
1050 {
1051 mutt_perror("%s", buf_string(pgptmpfile));
1052 mutt_file_fclose(&fp_pgp_err);
1053 goto cleanup;
1054 }
1055
1056 /* Position the stream at the beginning of the body, and send the data to
1057 * the temporary file. */
1058
1059 if (!mutt_file_seek(state->fp_in, a->offset, SEEK_SET))
1060 {
1061 mutt_file_fclose(&fp_pgp_tmp);
1062 mutt_file_fclose(&fp_pgp_err);
1063 goto cleanup;
1064 }
1065 mutt_file_copy_bytes(state->fp_in, fp_pgp_tmp, a->length);
1066 mutt_file_fclose(&fp_pgp_tmp);
1067
1068 pid = pgp_invoke_decrypt(&fp_pgp_in, &fp_pgp_out, NULL, -1, -1,
1069 fileno(fp_pgp_err), buf_string(pgptmpfile));
1070 if (pid == -1)
1071 {
1072 mutt_file_fclose(&fp_pgp_err);
1073 unlink(buf_string(pgptmpfile));
1074 if (state->flags & STATE_DISPLAY)
1075 {
1076 state_attach_puts(state, _("[-- Error: could not create a PGP subprocess --]\n\n"));
1077 }
1078 goto cleanup;
1079 }
1080
1081 /* send the PGP passphrase to the subprocess. Never do this if the agent is
1082 * active, because this might lead to a passphrase send as the message. */
1083 if (!pgp_use_gpg_agent())
1084 fputs(PgpPass, fp_pgp_in);
1085 fputc('\n', fp_pgp_in);
1086 mutt_file_fclose(&fp_pgp_in);
1087
1088 /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
1089 * read_mime_header has a hard time parsing the message. */
1090 while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1091 {
1092 size_t len = mutt_str_len(buf);
1093 if ((len > 1) && (buf[len - 2] == '\r'))
1094 strcpy(buf + len - 2, "\n");
1095 fputs(buf, fp_out);
1096 }
1097
1098 mutt_file_fclose(&fp_pgp_out);
1099
1100 rv = filter_wait(pid);
1101 const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
1102 if (c_pgp_use_gpg_agent)
1104
1105 mutt_file_unlink(buf_string(pgptmpfile));
1106
1107 fflush(fp_pgp_err);
1108 rewind(fp_pgp_err);
1109 if (pgp_check_decryption_okay(fp_pgp_err) < 0)
1110 {
1111 mutt_error(_("Decryption failed"));
1113 mutt_file_fclose(&fp_pgp_err);
1114 goto cleanup;
1115 }
1116
1117 if (state->flags & STATE_DISPLAY)
1118 {
1119 rewind(fp_pgp_err);
1120 if ((pgp_copy_checksig(fp_pgp_err, state->fp_out) == 0) && !rv)
1121 p->goodsig = true;
1122 else
1123 p->goodsig = false;
1124 state_attach_puts(state, _("[-- End of PGP output --]\n\n"));
1125 }
1126 mutt_file_fclose(&fp_pgp_err);
1127
1128 fflush(fp_out);
1129 rewind(fp_out);
1130
1131 if (fgetc(fp_out) == EOF)
1132 {
1133 mutt_error(_("Decryption failed"));
1135 goto cleanup;
1136 }
1137
1138 rewind(fp_out);
1139 const long size = mutt_file_get_size_fp(fp_out);
1140 if (size == 0)
1141 {
1142 goto cleanup;
1143 }
1144
1145 tattach = mutt_read_mime_header(fp_out, 0);
1146 if (tattach)
1147 {
1148 /* Need to set the length of this body part. */
1149 tattach->length = size - tattach->offset;
1150
1151 /* See if we need to recurse on this MIME part. */
1152 mutt_parse_part(fp_out, tattach);
1153 }
1154
1155cleanup:
1156 buf_pool_release(&pgptmpfile);
1157 return tattach;
1158}
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:100
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1748
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1318
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:252
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1578
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:771
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:219
void pgp_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition: pgp.c:76
#define mutt_error(...)
Definition: logging2.h:92
#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:103
#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:545
static char PgpPass[1024]
Cached PGP Passphrase.
Definition: pgp.c:69
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:251
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:127
static int pgp_check_decryption_okay(FILE *fp_in)
Check GPG output for status codes.
Definition: pgp.c:357
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:300
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. 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:

Variable Documentation

◆ PgpPass

char PgpPass[1024]
static

Cached PGP Passphrase.

Definition at line 69 of file pgp.c.

◆ PgpExptime

time_t PgpExptime = 0
static

Unix time when PgpPass expires.

Definition at line 71 of file pgp.c.