NeoMutt  2022-04-29-249-gaae397
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 "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 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 mutt_envlist_set("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: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 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 mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
273
274 if (mutt_strn_equal(line, "[GNUPG:] ", 9))
275 continue;
276 fputs(line, fp_out);
277 fputc('\n', fp_out);
278 }
279 FREE(&line);
280 }
281 else
282 {
283 mutt_debug(LL_DEBUG2, "No pattern\n");
284 mutt_file_copy_stream(fp_in, fp_out);
285 rc = 1;
286 }
287
288 return rc;
289}
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:260
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ 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:631
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c: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 301 of file pgp.c.

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

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

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

◆ pgp_check_traditional_one_body()

static bool pgp_check_traditional_one_body ( FILE *  fp,
struct Body b 
)
static

Check the body of an inline PGP message.

Parameters
fpFile to read
bBody to populate
Return values
trueSuccess
falseError

Definition at line 785 of file pgp.c.

786{
787 struct Buffer *tempfile = NULL;
788 char buf[8192] = { 0 };
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
845cleanup:
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:152
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1030
@ MUTT_SAVE_NO_FLAGS
No flags set.
Definition: mutt_attach.h:57
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_extract_keys_from_attachment()

static void pgp_extract_keys_from_attachment ( FILE *  fp,
struct Body top 
)
static

Extract pgp keys from messages/attachments.

Parameters
fpFile to read from
topTop Attachment

Definition at line 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 {
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
978cleanup:
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:387
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
void pgp_class_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import() -.
Definition: pgpinvoke.c:408
#define mutt_perror(...)
Definition: logging.h:88
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
Keep track when processing files.
Definition: state.h:46
FILE * fp_out
File to write to.
Definition: state.h:48
FILE * fp_in
File to read from.
Definition: state.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ pgp_decrypt_part()

static struct Body * pgp_decrypt_part ( struct Body a,
struct State s,
FILE *  fp_out,
struct Body p 
)
static

Decrypt part of a PGP message.

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

Definition at line 1008 of file pgp.c.

1010{
1011 if (!a || !s || !fp_out || !p)
1012 return NULL;
1013
1014 char buf[1024] = { 0 };
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 {
1057 state_attach_puts(s, _("[-- Error: could not create a PGP subprocess --]\n\n"));
1058 }
1059 goto cleanup;
1060 }
1061
1062 /* send the PGP passphrase to the subprocess. Never do this if the agent is
1063 * active, because this might lead to a passphrase send as the message. */
1064 if (!pgp_use_gpg_agent())
1065 fputs(PgpPass, fp_pgp_in);
1066 fputc('\n', fp_pgp_in);
1067 mutt_file_fclose(&fp_pgp_in);
1068
1069 /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
1070 * read_mime_header has a hard time parsing the message. */
1071 while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1072 {
1073 size_t len = mutt_str_len(buf);
1074 if ((len > 1) && (buf[len - 2] == '\r'))
1075 strcpy(buf + len - 2, "\n");
1076 fputs(buf, fp_out);
1077 }
1078
1079 mutt_file_fclose(&fp_pgp_out);
1080
1081 rv = filter_wait(pid);
1082 const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
1083 if (c_pgp_use_gpg_agent)
1085
1087
1088 fflush(fp_pgp_err);
1089 rewind(fp_pgp_err);
1090 if (pgp_check_decryption_okay(fp_pgp_err) < 0)
1091 {
1092 mutt_error(_("Decryption failed"));
1094 mutt_file_fclose(&fp_pgp_err);
1095 goto cleanup;
1096 }
1097
1098 if (s->flags & MUTT_DISPLAY)
1099 {
1100 rewind(fp_pgp_err);
1101 if ((pgp_copy_checksig(fp_pgp_err, s->fp_out) == 0) && !rv)
1102 p->goodsig = true;
1103 else
1104 p->goodsig = false;
1105 state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
1106 }
1107 mutt_file_fclose(&fp_pgp_err);
1108
1109 fflush(fp_out);
1110 rewind(fp_out);
1111
1112 if (fgetc(fp_out) == EOF)
1113 {
1114 mutt_error(_("Decryption failed"));
1116 goto cleanup;
1117 }
1118
1119 rewind(fp_out);
1120 const long size = mutt_file_get_size_fp(fp_out);
1121 if (size == 0)
1122 {
1123 goto cleanup;
1124 }
1125
1126 tattach = mutt_read_mime_header(fp_out, 0);
1127 if (tattach)
1128 {
1129 /* Need to set the length of this body part. */
1130 tattach->length = size - tattach->offset;
1131
1132 /* See if we need to recurse on this MIME part. */
1133 mutt_parse_part(fp_out, tattach);
1134 }
1135
1136cleanup:
1137 mutt_buffer_pool_release(&pgptmpfile);
1138 return tattach;
1139}
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:162
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:230
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1569
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define mutt_file_mkstemp()
Definition: file.h:112
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase() -.
Definition: pgp.c:75
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:100
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1736
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1317
char PgpPass[1024]
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:353
pid_t pgp_invoke_decrypt(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname)
Use PGP to decrypt a file.
Definition: pgpinvoke.c:302
The body of an email.
Definition: body.h:36
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
bool goodsig
Good cryptographic signature.
Definition: body.h:45
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ PgpPass

char PgpPass[1024]

Definition at line 69 of file pgp.c.

◆ PgpExptime

time_t PgpExptime = 0

Definition at line 70 of file pgp.c.