NeoMutt
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)
 Implements CryptModuleSpecs::void_passphrase() -.
 
bool pgp_class_valid_passphrase (void)
 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 *m, struct State *state)
 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)
 Implements CryptModuleSpecs::pgp_check_traditional() -.
 
int pgp_class_verify_one (struct Body *sigbdy, struct State *state, const char *tempfile)
 Implements CryptModuleSpecs::verify_one() -.
 
static void pgp_extract_keys_from_attachment (FILE *fp, struct Body *top)
 Extract pgp keys from messages/attachments.
 
void pgp_class_extract_key_from_attachment (FILE *fp, struct Body *top)
 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 **cur)
 Implements CryptModuleSpecs::decrypt_mime() -.
 
int pgp_class_encrypted_handler (struct Body *a, struct State *state)
 Implements CryptModuleSpecs::encrypted_handler() -.
 
struct Bodypgp_class_sign_message (struct Body *a, const struct AddressList *from)
 Implements CryptModuleSpecs::sign_message() -.
 
char * pgp_class_find_keys (const struct AddressList *addrlist, bool oppenc_mode)
 Implements CryptModuleSpecs::find_keys() -.
 
struct Bodypgp_class_encrypt_message (struct Body *a, char *keylist, bool sign, const struct AddressList *from)
 Implements CryptModuleSpecs::pgp_encrypt_message() -.
 
struct Bodypgp_class_traditional_encryptsign (struct Body *a, SecurityFlags flags, char *keylist)
 Implements CryptModuleSpecs::pgp_traditional_encryptsign() -.
 
SecurityFlags pgp_class_send_menu (struct Email *e)
 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
  • 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 128 of file pgp.c.

129{
130 char *tty = NULL;
131
132 /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
133 const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
134 if (!c_pgp_use_gpg_agent)
135 return false;
136
137 tty = ttyname(0);
138 if (tty)
139 {
140 setenv("GPG_TTY", tty, 0);
141 envlist_set(&EnvList, "GPG_TTY", tty, false);
142 }
143
144 return true;
145}
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:87
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:85
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 152 of file pgp.c.

153{
154 const bool c_pgp_ignore_subkeys = cs_subset_bool(NeoMutt->sub, "pgp_ignore_subkeys");
155 if ((k->flags & KEYFLAG_SUBKEY) && k->parent && c_pgp_ignore_subkeys)
156 k = k->parent;
157
158 return k;
159}
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:135
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 166 of file pgp.c.

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

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

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

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

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

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

253{
254 if (!fp_in || !fp_out)
255 return -1;
256
257 int rc = -1;
258
259 const struct Regex *c_pgp_good_sign = cs_subset_regex(NeoMutt->sub, "pgp_good_sign");
260 if (c_pgp_good_sign && c_pgp_good_sign->regex)
261 {
262 char *line = NULL;
263 size_t linelen;
264
265 while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
266 {
267 if (mutt_regex_match(c_pgp_good_sign, line))
268 {
269 mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
270 rc = 0;
271 }
272 else
273 {
274 mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
275 }
276
277 if (mutt_strn_equal(line, "[GNUPG:] ", 9))
278 continue;
279 fputs(line, fp_out);
280 fputc('\n', fp_out);
281 }
282 FREE(&line);
283 }
284 else
285 {
286 mutt_debug(LL_DEBUG2, "No pattern\n");
287 mutt_file_copy_stream(fp_in, fp_out);
288 rc = 1;
289 }
290
291 return rc;
292}
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:262
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:763
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:39
#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:636
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:497
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 304 of file pgp.c.

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

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

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

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

Extract pgp keys from messages/attachments.

Parameters
fpFile to read from
topTop Attachment

Definition at line 973 of file pgp.c.

974{
975 struct State state = { 0 };
976 struct Buffer *tempfname = buf_pool_get();
977
978 buf_mktemp(tempfname);
979 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfname), "w");
980 if (!fp_tmp)
981 {
982 mutt_perror("%s", buf_string(tempfname));
983 goto cleanup;
984 }
985
986 state.fp_in = fp;
987 state.fp_out = fp_tmp;
988
989 mutt_body_handler(top, &state);
990
991 mutt_file_fclose(&fp_tmp);
992
995
996 mutt_file_unlink(buf_string(tempfname));
997
998cleanup:
999 buf_pool_release(&tempfname);
1000}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:188
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:636
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:196
void pgp_class_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import() -.
Definition: pgpinvoke.c:419
#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:1618
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 1028 of file pgp.c.

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

◆ PgpExptime

time_t PgpExptime = 0
static

Unix time when PgpPass expires.

Definition at line 72 of file pgp.c.