NeoMutt  2024-04-25-89-g194907
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pgpinvoke.c
Go to the documentation of this file.
1
33#include "config.h"
34#include <fcntl.h>
35#include <stdbool.h>
36#include <stdio.h>
37#include <unistd.h>
38#include "mutt/lib.h"
39#include "address/lib.h"
40#include "config/lib.h"
41#include "core/lib.h"
42#include "gui/lib.h"
43#include "pgpinvoke.h"
44#include "lib.h"
45#include "expando/lib.h"
46#include "globals.h"
47#include "mutt_logging.h"
48#include "pgpkey.h"
49#include "protos.h"
50#ifdef CRYPT_BACKEND_CLASSIC_PGP
51#include "pgp.h"
52#endif
53
55
59void pgp_command_a(const struct ExpandoNode *node, void *data,
60 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
61{
62 const struct PgpCommandContext *cctx = data;
63
64 const char *s = cctx->signas;
65 buf_strcpy(buf, s);
66}
67
71void pgp_command_f(const struct ExpandoNode *node, void *data,
72 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
73{
74 const struct PgpCommandContext *cctx = data;
75
76 const char *s = cctx->fname;
77 buf_strcpy(buf, s);
78}
79
83void pgp_command_p(const struct ExpandoNode *node, void *data,
84 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
85{
86 const struct PgpCommandContext *cctx = data;
87
88 const char *s = cctx->need_passphrase ? "PGPPASSFD=0" : "";
89 buf_strcpy(buf, s);
90}
91
95void pgp_command_r(const struct ExpandoNode *node, void *data,
96 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
97{
98 const struct PgpCommandContext *cctx = data;
99
100 const char *s = cctx->ids;
101 buf_strcpy(buf, s);
102}
103
107void pgp_command_s(const struct ExpandoNode *node, void *data,
108 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
109{
110 const struct PgpCommandContext *cctx = data;
111
112 const char *s = cctx->sig_fname;
113 buf_strcpy(buf, s);
114}
115
122static void mutt_pgp_command(struct Buffer *buf, struct PgpCommandContext *cctx,
123 const struct Expando *exp)
124{
126 mutt_debug(LL_DEBUG2, "%s\n", buf_string(buf));
127}
128
148static pid_t pgp_invoke(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
149 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err,
150 bool need_passphrase, const char *fname, const char *sig_fname,
151 const char *ids, const struct Expando *exp)
152{
153 struct PgpCommandContext cctx = { 0 };
154
155 if (!exp)
156 return (pid_t) -1;
157
159 cctx.fname = fname;
160 cctx.sig_fname = sig_fname;
161 const char *const c_pgp_sign_as = cs_subset_string(NeoMutt->sub, "pgp_sign_as");
162 const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
163 if (c_pgp_sign_as)
164 cctx.signas = c_pgp_sign_as;
165 else
166 cctx.signas = c_pgp_default_key;
167 cctx.ids = ids;
168
169 struct Buffer *cmd = buf_pool_get();
170 mutt_pgp_command(cmd, &cctx, exp);
171
172 pid_t pid = filter_create_fd(buf_string(cmd), fp_pgp_in, fp_pgp_out, fp_pgp_err,
173 fd_pgp_in, fd_pgp_out, fd_pgp_err, EnvList);
174 buf_pool_release(&cmd);
175 return pid;
176}
177
178/*
179 * The exported interface.
180 *
181 * This is historic and may be removed at some point.
182 */
183
200pid_t pgp_invoke_decode(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
201 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err,
202 const char *fname, bool need_passphrase)
203{
204 const struct Expando *c_pgp_decode_command = cs_subset_expando(NeoMutt->sub, "pgp_decode_command");
205 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out, fd_pgp_err,
206 need_passphrase, fname, NULL, NULL, c_pgp_decode_command);
207}
208
225pid_t pgp_invoke_verify(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
226 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err,
227 const char *fname, const char *sig_fname)
228{
229 const struct Expando *c_pgp_verify_command = cs_subset_expando(NeoMutt->sub, "pgp_verify_command");
230 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
231 fd_pgp_err, false, fname, sig_fname, NULL, c_pgp_verify_command);
232}
233
249pid_t pgp_invoke_decrypt(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
250 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname)
251{
252 const struct Expando *c_pgp_decrypt_command = cs_subset_expando(NeoMutt->sub, "pgp_decrypt_command");
253 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
254 fd_pgp_err, true, fname, NULL, NULL, c_pgp_decrypt_command);
255}
256
272pid_t pgp_invoke_sign(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
273 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname)
274{
275 const struct Expando *c_pgp_sign_command = cs_subset_expando(NeoMutt->sub, "pgp_sign_command");
276 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
277 fd_pgp_err, true, fname, NULL, NULL, c_pgp_sign_command);
278}
279
297pid_t pgp_invoke_encrypt(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
298 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err,
299 const char *fname, const char *uids, bool sign)
300{
301 if (sign)
302 {
303 const struct Expando *c_pgp_encrypt_sign_command = cs_subset_expando(NeoMutt->sub, "pgp_encrypt_sign_command");
304 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
305 fd_pgp_err, true, fname, NULL, uids, c_pgp_encrypt_sign_command);
306 }
307 else
308 {
309 const struct Expando *c_pgp_encrypt_only_command = cs_subset_expando(NeoMutt->sub, "pgp_encrypt_only_command");
310 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
311 fd_pgp_err, false, fname, NULL, uids, c_pgp_encrypt_only_command);
312 }
313}
314
332pid_t pgp_invoke_traditional(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
333 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err,
334 const char *fname, const char *uids, SecurityFlags flags)
335{
336 if (flags & SEC_ENCRYPT)
337 {
338 const struct Expando *c_pgp_encrypt_only_command = cs_subset_expando(NeoMutt->sub, "pgp_encrypt_only_command");
339 const struct Expando *c_pgp_encrypt_sign_command = cs_subset_expando(NeoMutt->sub, "pgp_encrypt_sign_command");
340 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
341 fd_pgp_err, (flags & SEC_SIGN), fname, NULL, uids,
342 (flags & SEC_SIGN) ? c_pgp_encrypt_sign_command : c_pgp_encrypt_only_command);
343 }
344 else
345 {
346 const struct Expando *c_pgp_clear_sign_command = cs_subset_expando(NeoMutt->sub, "pgp_clear_sign_command");
347 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
348 fd_pgp_err, true, fname, NULL, NULL, c_pgp_clear_sign_command);
349 }
350}
351
355void pgp_class_invoke_import(const char *fname)
356{
357 struct PgpCommandContext cctx = { 0 };
358
359 struct Buffer *buf_fname = buf_pool_get();
360 struct Buffer *cmd = buf_pool_get();
361
362 buf_quote_filename(buf_fname, fname, true);
363 cctx.fname = buf_string(buf_fname);
364 const char *const c_pgp_sign_as = cs_subset_string(NeoMutt->sub, "pgp_sign_as");
365 const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
366 if (c_pgp_sign_as)
367 cctx.signas = c_pgp_sign_as;
368 else
369 cctx.signas = c_pgp_default_key;
370
371 const struct Expando *c_pgp_import_command = cs_subset_expando(NeoMutt->sub, "pgp_import_command");
372 mutt_pgp_command(cmd, &cctx, c_pgp_import_command);
373 if (mutt_system(buf_string(cmd)) != 0)
374 mutt_debug(LL_DEBUG1, "Error running \"%s\"\n", buf_string(cmd));
375
376 buf_pool_release(&buf_fname);
377 buf_pool_release(&cmd);
378}
379
384{
385 struct Buffer *personal = NULL;
386 struct PgpCommandContext cctx = { 0 };
387
388 const struct Expando *c_pgp_get_keys_command = cs_subset_expando(NeoMutt->sub, "pgp_get_keys_command");
389 if (!c_pgp_get_keys_command)
390 return;
391
392 struct Buffer *buf = buf_pool_get();
393 struct Buffer *cmd = buf_pool_get();
394 personal = addr->personal;
395 addr->personal = NULL;
396
397 struct Buffer *tmp = buf_pool_get();
398 mutt_addr_to_local(addr);
399 mutt_addr_write(tmp, addr, false);
400 buf_quote_filename(buf, buf_string(tmp), true);
401 buf_pool_release(&tmp);
402
403 addr->personal = personal;
404
405 cctx.ids = buf_string(buf);
406
407 mutt_pgp_command(cmd, &cctx, c_pgp_get_keys_command);
408
409 int fd_null = open("/dev/null", O_RDWR);
410
411 if (!isendwin())
412 mutt_message(_("Fetching PGP key..."));
413
414 if (mutt_system(buf_string(cmd)) != 0)
415 mutt_debug(LL_DEBUG1, "Error running \"%s\"\n", buf_string(cmd));
416
417 if (!isendwin())
419
420 if (fd_null >= 0)
421 close(fd_null);
422
423 buf_pool_release(&buf);
424 buf_pool_release(&cmd);
425}
426
442pid_t pgp_invoke_export(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
443 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *uids)
444{
445 const struct Expando *c_pgp_export_command = cs_subset_expando(NeoMutt->sub, "pgp_export_command");
446 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
447 fd_pgp_err, false, NULL, NULL, uids, c_pgp_export_command);
448}
449
465pid_t pgp_invoke_verify_key(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
466 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *uids)
467{
468 const struct Expando *c_pgp_verify_key_command = cs_subset_expando(NeoMutt->sub, "pgp_verify_key_command");
469 return pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in, fd_pgp_out,
470 fd_pgp_err, false, NULL, NULL, uids, c_pgp_verify_key_command);
471}
472
489pid_t pgp_invoke_list_keys(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err,
490 int fd_pgp_in, int fd_pgp_out, int fd_pgp_err,
491 enum PgpRing keyring, struct ListHead *hints)
492{
493 struct Buffer *uids = buf_pool_get();
494 struct Buffer *quoted = buf_pool_get();
495
496 struct ListNode *np = NULL;
497 STAILQ_FOREACH(np, hints, entries)
498 {
499 buf_quote_filename(quoted, (char *) np->data, true);
500 buf_addstr(uids, buf_string(quoted));
501 if (STAILQ_NEXT(np, entries))
502 buf_addch(uids, ' ');
503 }
504
505 const struct Expando *c_pgp_list_pubring_command = cs_subset_expando(NeoMutt->sub, "pgp_list_pubring_command");
506 const struct Expando *c_pgp_list_secring_command = cs_subset_expando(NeoMutt->sub, "pgp_list_secring_command");
507 pid_t rc = pgp_invoke(fp_pgp_in, fp_pgp_out, fp_pgp_err, fd_pgp_in,
508 fd_pgp_out, fd_pgp_err, 0, NULL, NULL, buf_string(uids),
509 (keyring == PGP_SECRING) ? c_pgp_list_secring_command :
510 c_pgp_list_pubring_command);
511
512 buf_pool_release(&uids);
513 buf_pool_release(&quoted);
514 return rc;
515}
516
523 // clang-format off
529 { -1, -1, NULL, NULL },
530 // clang-format on
531};
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1050
bool mutt_addr_to_local(struct Address *a)
Convert an Address from Punycode.
Definition: address.c:1340
Email Address Handling.
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:357
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
@ ED_PGP_CMD
Pgp Command ED_PGC_ ExpandoDataPgpCmd.
Definition: domain.h:53
Parse Expando string.
int expando_render(const struct Expando *exp, const struct ExpandoRenderData *rdata, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition: expando.c:109
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:933
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
void pgp_class_invoke_getkeys(struct Address *addr)
Run a command to download a PGP key - Implements CryptModuleSpecs::pgp_invoke_getkeys() -.
Definition: pgpinvoke.c:383
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:355
void pgp_command_s(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
PGP Command: Filename of signature - Implements ExpandoRenderData::get_string() -.
Definition: pgpinvoke.c:107
void pgp_command_r(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
PGP Command: key IDs - Implements ExpandoRenderData::get_string() -.
Definition: pgpinvoke.c:95
void pgp_command_f(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
PGP Command: Filename of message - Implements ExpandoRenderData::get_string() -.
Definition: pgpinvoke.c:71
void pgp_command_a(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
PGP Command: $pgp_sign_as or $pgp_default_key - Implements ExpandoRenderData::get_string() -.
Definition: pgpinvoke.c:59
void pgp_command_p(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
PGP Command: PGPPASSFD=0 if passphrase is needed - Implements ExpandoRenderData::get_string() -.
Definition: pgpinvoke.c:83
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
Convenience wrapper for the gui headers.
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr, char **envlist)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:62
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
NeoMutt Logging.
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:76
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
PGP sign, encrypt, check routines.
@ ED_PGC_KEY_IDS
PgpCommandContext.ids.
Definition: pgp.h:60
@ ED_PGC_FILE_SIGNATURE
PgpCommandContext.sig_fname.
Definition: pgp.h:59
@ ED_PGC_NEED_PASS
PgpCommandContext.need_passphrase.
Definition: pgp.h:61
@ ED_PGC_SIGN_AS
PgpCommandContext.signas.
Definition: pgp.h:62
@ ED_PGC_FILE_MESSAGE
PgpCommandContext.fname.
Definition: pgp.h:58
pid_t pgp_invoke_verify_key(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 *uids)
Use PGP to verify a key.
Definition: pgpinvoke.c:465
pid_t pgp_invoke_encrypt(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, const char *uids, bool sign)
Use PGP to encrypt a file.
Definition: pgpinvoke.c:297
const struct ExpandoRenderData PgpCommandRenderData[]
Callbacks for PGP Command Expandos.
Definition: pgpinvoke.c:54
pid_t pgp_invoke_decode(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, bool need_passphrase)
Use PGP to decode a message.
Definition: pgpinvoke.c:200
pid_t pgp_invoke_traditional(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, const char *uids, SecurityFlags flags)
Use PGP to create in inline-signed message.
Definition: pgpinvoke.c:332
static pid_t pgp_invoke(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, bool need_passphrase, const char *fname, const char *sig_fname, const char *ids, const struct Expando *exp)
Run a PGP command.
Definition: pgpinvoke.c:148
pid_t pgp_invoke_sign(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 sign a file.
Definition: pgpinvoke.c:272
pid_t pgp_invoke_verify(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, const char *sig_fname)
Use PGP to verify a message.
Definition: pgpinvoke.c:225
pid_t pgp_invoke_export(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 *uids)
Use PGP to export a key from the user's keyring.
Definition: pgpinvoke.c:442
static void mutt_pgp_command(struct Buffer *buf, struct PgpCommandContext *cctx, const struct Expando *exp)
Prepare a PGP Command.
Definition: pgpinvoke.c:122
pid_t pgp_invoke_list_keys(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, enum PgpRing keyring, struct ListHead *hints)
Find matching PGP Keys.
Definition: pgpinvoke.c:489
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:249
Wrapper around calls to external PGP program.
PGP key management routines.
PgpRing
PGP ring type.
Definition: pgpkey.h:38
@ PGP_SECRING
Secret keys.
Definition: pgpkey.h:40
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
Prototypes for many functions.
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:52
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: render.h:33
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: render.h:32
Key value store.
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
String manipulation buffer.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:39
Basic Expando Node.
Definition: node.h:69
Parsed Expando trees.
Definition: expando.h:41
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
Data for a PGP command.
Definition: pgp.h:43
bool need_passphrase
p
Definition: pgp.h:44
const char * signas
a
Definition: pgp.h:47
const char * fname
f
Definition: pgp.h:45
const char * ids
r
Definition: pgp.h:48
const char * sig_fname
s
Definition: pgp.h:46