NeoMutt  2023-03-22-27-g3cb248
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 "enter/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)
 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 *state, char *charset)
 Copy a clearsigned message, stripping the signature. More...
 
int pgp_class_application_handler (struct Body *m, struct State *state)
 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 *state, 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 *state, 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 *state)
 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 126 of file pgp.c.

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

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

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

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

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

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

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

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

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

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

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

420{
421 char buf[8192] = { 0 };
422 bool complete, armor_header;
423
424 rewind(fp_in);
425
426 /* fromcode comes from the MIME Content-Type charset label. It might
427 * be a wrong label, so we want the ability to do corrections via
428 * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
429 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
430 struct FgetConv *fc = mutt_ch_fgetconv_open(fp_in, charset, c_charset, MUTT_ICONV_HOOK_FROM);
431
432 for (complete = true, armor_header = true;
433 mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
434 {
435 if (!complete)
436 {
437 if (!armor_header)
438 state_puts(state, buf);
439 continue;
440 }
441
442 if (mutt_str_equal(buf, "-----BEGIN PGP SIGNATURE-----\n"))
443 break;
444
445 if (armor_header)
446 {
447 char *p = mutt_str_skip_whitespace(buf);
448 if (*p == '\0')
449 armor_header = false;
450 continue;
451 }
452
453 if (state->prefix)
454 state_puts(state, state->prefix);
455
456 if ((buf[0] == '-') && (buf[1] == ' '))
457 state_puts(state, buf + 2);
458 else
459 state_puts(state, buf);
460 }
461
463}
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:888
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:856
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file's charset into a string buffer.
Definition: charset.c:970
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
#define state_puts(STATE, STR)
Definition: state.h:57
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:622
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:50
+ 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 794 of file pgp.c.

795{
796 struct Buffer *tempfile = NULL;
797 char buf[8192] = { 0 };
798 bool rc = false;
799
800 bool sgn = false;
801 bool enc = false;
802 bool key = false;
803
804 if (b->type != TYPE_TEXT)
805 goto cleanup;
806
807 tempfile = mutt_buffer_pool_get();
808 mutt_buffer_mktemp(tempfile);
811 {
812 unlink(mutt_buffer_string(tempfile));
813 goto cleanup;
814 }
815
816 FILE *fp_tmp = fopen(mutt_buffer_string(tempfile), "r");
817 if (!fp_tmp)
818 {
819 unlink(mutt_buffer_string(tempfile));
820 goto cleanup;
821 }
822
823 while (fgets(buf, sizeof(buf), fp_tmp))
824 {
825 size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
826 if (plen != 0)
827 {
828 if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
829 enc = true;
830 else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
831 sgn = true;
832 else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
833 key = true;
834 }
835 }
836 mutt_file_fclose(&fp_tmp);
837 unlink(mutt_buffer_string(tempfile));
838
839 if (!enc && !sgn && !key)
840 goto cleanup;
841
842 /* fix the content type */
843
844 mutt_param_set(&b->parameter, "format", "fixed");
845 if (enc)
846 mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
847 else if (sgn)
848 mutt_param_set(&b->parameter, "x-action", "pgp-signed");
849 else if (key)
850 mutt_param_set(&b->parameter, "x-action", "pgp-keys");
851
852 rc = true;
853
854cleanup:
855 mutt_buffer_pool_release(&tempfile);
856 return rc;
857}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
#define STATE_NO_FLAGS
No flags are set.
Definition: state.h:31
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, StateFlags flags, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1048
@ 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: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
#define mutt_buffer_mktemp(buf)
Definition: tmp.h:37
+ 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 964 of file pgp.c.

965{
966 struct State state = { 0 };
967 struct Buffer *tempfname = mutt_buffer_pool_get();
968
969 mutt_buffer_mktemp(tempfname);
970 FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfname), "w");
971 if (!fp_tmp)
972 {
974 goto cleanup;
975 }
976
977 state.fp_in = fp;
978 state.fp_out = fp_tmp;
979
980 mutt_body_handler(top, &state);
981
982 mutt_file_fclose(&fp_tmp);
983
986
988
989cleanup:
990 mutt_buffer_pool_release(&tempfname);
991}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:386
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:193
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 *state)
Handler for the Body of an email.
Definition: handler.c:1619
Keep track when processing files.
Definition: state.h:47
FILE * fp_out
File to write to.
Definition: state.h:49
FILE * fp_in
File to read from.
Definition: state.h:48
+ 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 1019 of file pgp.c.

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