NeoMutt  2023-05-17-16-g61469c
Teaching an old dog new tricks
DOXYGEN
pgp_traditional_encryptsign()

Create an inline PGP encrypted, signed email. More...

+ Collaboration diagram for pgp_traditional_encryptsign():

Functions

struct Bodypgp_class_traditional_encryptsign (struct Body *a, SecurityFlags flags, char *keylist)
 Implements CryptModuleSpecs::pgp_traditional_encryptsign() -. More...
 

Detailed Description

Create an inline PGP encrypted, signed email.

Parameters
aBody of the email
flagsFlags, see SecurityFlags
keylistList of keys to encrypt to (space-separated)
Return values
ptrNew encrypted/siged Body
NULLError

Function Documentation

◆ pgp_class_traditional_encryptsign()

struct Body * pgp_class_traditional_encryptsign ( struct Body a,
SecurityFlags  flags,
char *  keylist 
)

Implements CryptModuleSpecs::pgp_traditional_encryptsign() -.

Definition at line 1725 of file pgp.c.

1726{
1727 struct Body *b = NULL;
1728 char body_charset[256] = { 0 };
1729 const char *from_charset = NULL;
1730 const char *send_charset = NULL;
1731 bool empty = false;
1732 bool err;
1733 char buf[256] = { 0 };
1734 pid_t pid;
1735 struct Buffer *pgpinfile = buf_pool_get();
1736 struct Buffer *pgpoutfile = buf_pool_get();
1737
1738 if (a->type != TYPE_TEXT)
1739 goto cleanup;
1740 if (!mutt_istr_equal(a->subtype, "plain"))
1741 goto cleanup;
1742
1743 FILE *fp_body = fopen(a->filename, "r");
1744 if (!fp_body)
1745 {
1747 goto cleanup;
1748 }
1749
1750 buf_mktemp(pgpinfile);
1751 FILE *fp_pgp_in = mutt_file_fopen(buf_string(pgpinfile), "w");
1752 if (!fp_pgp_in)
1753 {
1754 mutt_perror(buf_string(pgpinfile));
1755 mutt_file_fclose(&fp_body);
1756 goto cleanup;
1757 }
1758
1759 /* The following code is really correct: If noconv is set,
1760 * a's charset parameter contains the on-disk character set, and
1761 * we have to convert from that to utf-8. If noconv is not set,
1762 * we have to convert from $charset to utf-8. */
1763
1764 mutt_body_get_charset(a, body_charset, sizeof(body_charset));
1765 if (a->noconv)
1766 from_charset = body_charset;
1767 else
1768 from_charset = cc_charset();
1769
1770 if (mutt_ch_is_us_ascii(body_charset))
1771 {
1772 send_charset = "us-ascii";
1773 mutt_file_copy_stream(fp_body, fp_pgp_in);
1774 }
1775 else
1776 {
1777 int c;
1778 struct FgetConv *fc = NULL;
1779
1780 if (flags & SEC_ENCRYPT)
1781 send_charset = "us-ascii";
1782 else
1783 send_charset = "utf-8";
1784
1785 /* fromcode is assumed to be correct: we set flags to 0 */
1786 fc = mutt_ch_fgetconv_open(fp_body, from_charset, "utf-8", MUTT_ICONV_NO_FLAGS);
1787 while ((c = mutt_ch_fgetconv(fc)) != EOF)
1788 fputc(c, fp_pgp_in);
1789
1791 }
1792 mutt_file_fclose(&fp_body);
1793 mutt_file_fclose(&fp_pgp_in);
1794
1795 buf_mktemp(pgpoutfile);
1796 FILE *fp_pgp_out = mutt_file_fopen(buf_string(pgpoutfile), "w+");
1797 FILE *fp_pgp_err = mutt_file_mkstemp();
1798 if (!fp_pgp_out || !fp_pgp_err)
1799 {
1800 mutt_perror(fp_pgp_out ? "Can't create temporary file" : buf_string(pgpoutfile));
1801 unlink(buf_string(pgpinfile));
1802 if (fp_pgp_out)
1803 {
1804 mutt_file_fclose(&fp_pgp_out);
1805 unlink(buf_string(pgpoutfile));
1806 }
1807 mutt_file_fclose(&fp_pgp_err);
1808 goto cleanup;
1809 }
1810
1811 pid = pgp_invoke_traditional(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
1812 fileno(fp_pgp_err), buf_string(pgpinfile), keylist, flags);
1813 if (pid == -1)
1814 {
1815 mutt_perror(_("Can't invoke PGP"));
1816 mutt_file_fclose(&fp_pgp_out);
1817 mutt_file_fclose(&fp_pgp_err);
1818 mutt_file_unlink(buf_string(pgpinfile));
1819 unlink(buf_string(pgpoutfile));
1820 goto cleanup;
1821 }
1822
1823 if (pgp_use_gpg_agent())
1824 *PgpPass = '\0';
1825 if (flags & SEC_SIGN)
1826 fprintf(fp_pgp_in, "%s\n", PgpPass);
1827 mutt_file_fclose(&fp_pgp_in);
1828
1829 const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1830 if (filter_wait(pid) && c_pgp_check_exit)
1831 empty = true;
1832
1833 mutt_file_unlink(buf_string(pgpinfile));
1834
1835 fflush(fp_pgp_out);
1836 fflush(fp_pgp_err);
1837
1838 rewind(fp_pgp_out);
1839 rewind(fp_pgp_err);
1840
1841 if (!empty)
1842 empty = (fgetc(fp_pgp_out) == EOF);
1843 mutt_file_fclose(&fp_pgp_out);
1844
1845 err = false;
1846
1847 while (fgets(buf, sizeof(buf), fp_pgp_err))
1848 {
1849 err = true;
1850 fputs(buf, stdout);
1851 }
1852
1853 mutt_file_fclose(&fp_pgp_err);
1854
1855 if (err)
1857
1858 if (empty)
1859 {
1860 if (flags & SEC_SIGN)
1861 pgp_class_void_passphrase(); /* just in case */
1862 unlink(buf_string(pgpoutfile));
1863 goto cleanup;
1864 }
1865
1866 b = mutt_body_new();
1867
1868 b->encoding = ENC_7BIT;
1869
1870 b->type = TYPE_TEXT;
1871 b->subtype = mutt_str_dup("plain");
1872
1873 mutt_param_set(&b->parameter, "x-action",
1874 (flags & SEC_ENCRYPT) ? "pgp-encrypted" : "pgp-signed");
1875 mutt_param_set(&b->parameter, "charset", send_charset);
1876
1877 b->filename = buf_strdup(pgpoutfile);
1878
1880 b->unlink = true;
1881
1882 b->noconv = true;
1883 b->use_disp = false;
1884
1885 if (!(flags & SEC_ENCRYPT))
1886 b->encoding = a->encoding;
1887
1888cleanup:
1889 buf_pool_release(&pgpinfile);
1890 buf_pool_release(&pgpoutfile);
1891 return b;
1892}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:490
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
const char * cc_charset(void)
Get the cached value of $charset.
Definition: cache.c:106
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
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:76
#define mutt_perror(...)
Definition: logging2.h:88
@ ENC_7BIT
7-bit text
Definition: mime.h:49
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
@ DISP_NONE
No preferred disposition.
Definition: mime.h:65
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:956
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file's character set.
Definition: charset.c:974
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:924
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:97
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
static char PgpPass[1024]
Cached PGP Passphrase.
Definition: pgp.c:69
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:128
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:395
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:106
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:119
The body of an email.
Definition: body.h:36
bool noconv
Don't do character set conversion.
Definition: body.h:46
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:67
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:47
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
char * subtype
content-type subtype
Definition: body.h:60
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
Cursor for converting a file's encoding.
Definition: charset.h:41
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define buf_mktemp(buf)
Definition: tmp.h:37
#define mutt_file_mkstemp()
Definition: tmp.h:40
+ Here is the call graph for this function: