NeoMutt  2025-12-11-1059-g2f5469
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pgp_traditional_encryptsign()

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

Collaboration diagram for pgp_traditional_encryptsign():

Functions

struct Body * pgp_class_traditional_encryptsign (struct Body *b, SecurityFlags flags, char *keylist)
 Create an inline PGP encrypted, signed email - Implements CryptModuleSpecs::pgp_traditional_encryptsign() -.

Detailed Description

Create an inline PGP encrypted, signed email.

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

Function Documentation

◆ pgp_class_traditional_encryptsign()

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

Create an inline PGP encrypted, signed email - Implements CryptModuleSpecs::pgp_traditional_encryptsign() -.

Definition at line 1758 of file pgp.c.

1759{
1761 struct Body *b_enc = NULL;
1762 char body_charset[256] = { 0 };
1763 const char *from_charset = NULL;
1764 const char *send_charset = NULL;
1765 bool empty = false;
1766 bool err;
1767 char buf[256] = { 0 };
1768 pid_t pid;
1769 struct Buffer *pgpinfile = buf_pool_get();
1770 struct Buffer *pgpoutfile = buf_pool_get();
1771
1772 if (b->type != TYPE_TEXT)
1773 goto cleanup;
1774 if (!mutt_istr_equal(b->subtype, "plain"))
1775 goto cleanup;
1776
1777 FILE *fp_body = mutt_file_fopen(b->filename, "r");
1778 if (!fp_body)
1779 {
1780 mutt_perror("%s", b->filename);
1781 goto cleanup;
1782 }
1783
1784 buf_mktemp(pgpinfile);
1785 FILE *fp_pgp_in = mutt_file_fopen(buf_string(pgpinfile), "w");
1786 if (!fp_pgp_in)
1787 {
1788 mutt_perror("%s", buf_string(pgpinfile));
1789 mutt_file_fclose(&fp_body);
1790 goto cleanup;
1791 }
1792
1793 /* The following code is really correct: If noconv is set,
1794 * b's charset parameter contains the on-disk character set, and
1795 * we have to convert from that to utf-8. If noconv is not set,
1796 * we have to convert from $charset to utf-8. */
1797
1798 mutt_body_get_charset(b, body_charset, sizeof(body_charset));
1799 if (b->noconv)
1800 from_charset = body_charset;
1801 else
1802 from_charset = cc_charset();
1803
1804 if (mutt_ch_is_us_ascii(body_charset))
1805 {
1806 send_charset = "us-ascii";
1807 mutt_file_copy_stream(fp_body, fp_pgp_in);
1808 }
1809 else
1810 {
1811 int c;
1812 struct FgetConv *fc = NULL;
1813
1814 if (flags & SEC_ENCRYPT)
1815 send_charset = "us-ascii";
1816 else
1817 send_charset = "utf-8";
1818
1819 /* fromcode is assumed to be correct: we set flags to 0 */
1820 fc = mutt_ch_fgetconv_open(fp_body, from_charset, "utf-8", MUTT_ICONV_NONE);
1821 while ((c = mutt_ch_fgetconv(fc)) != EOF)
1822 fputc(c, fp_pgp_in);
1823
1825 }
1826 mutt_file_fclose(&fp_body);
1827 mutt_file_fclose(&fp_pgp_in);
1828
1829 buf_mktemp(pgpoutfile);
1830 FILE *fp_pgp_out = mutt_file_fopen(buf_string(pgpoutfile), "w+");
1831 FILE *fp_pgp_err = mutt_file_mkstemp();
1832 if (!fp_pgp_out || !fp_pgp_err)
1833 {
1834 mutt_perror("%s", fp_pgp_out ? "Can't create temporary file" : buf_string(pgpoutfile));
1835 unlink(buf_string(pgpinfile));
1836 if (fp_pgp_out)
1837 {
1838 mutt_file_fclose(&fp_pgp_out);
1839 unlink(buf_string(pgpoutfile));
1840 }
1841 mutt_file_fclose(&fp_pgp_err);
1842 goto cleanup;
1843 }
1844
1845 pid = pgp_invoke_traditional(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
1846 fileno(fp_pgp_err), buf_string(pgpinfile), keylist, flags);
1847 if (pid == -1)
1848 {
1849 mutt_perror(_("Can't invoke PGP"));
1850 mutt_file_fclose(&fp_pgp_out);
1851 mutt_file_fclose(&fp_pgp_err);
1852 mutt_file_unlink(buf_string(pgpinfile));
1853 unlink(buf_string(pgpoutfile));
1854 goto cleanup;
1855 }
1856
1857 if (pgp_use_gpg_agent())
1858 *mod_data->pgp_pass = '\0';
1859 if (flags & SEC_SIGN)
1860 fprintf(fp_pgp_in, "%s\n", mod_data->pgp_pass);
1861 mutt_file_fclose(&fp_pgp_in);
1862
1863 const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1864 if (filter_wait(pid) && c_pgp_check_exit)
1865 empty = true;
1866
1867 mutt_file_unlink(buf_string(pgpinfile));
1868
1869 fflush(fp_pgp_out);
1870 fflush(fp_pgp_err);
1871
1872 fseek(fp_pgp_out, 0, SEEK_SET);
1873 clearerr(fp_pgp_out);
1874 fseek(fp_pgp_err, 0, SEEK_SET);
1875 clearerr(fp_pgp_err);
1876
1877 if (!empty)
1878 empty = (fgetc(fp_pgp_out) == EOF);
1879 mutt_file_fclose(&fp_pgp_out);
1880
1881 err = false;
1882
1883 while (fgets(buf, sizeof(buf), fp_pgp_err))
1884 {
1885 err = true;
1886 fputs(buf, stdout);
1887 }
1888
1889 mutt_file_fclose(&fp_pgp_err);
1890
1891 if (err)
1893
1894 if (empty)
1895 {
1896 if (flags & SEC_SIGN)
1897 pgp_class_void_passphrase(); /* just in case */
1898 unlink(buf_string(pgpoutfile));
1899 goto cleanup;
1900 }
1901
1902 b_enc = mutt_body_new();
1903
1904 b_enc->encoding = ENC_7BIT;
1905
1906 b_enc->type = TYPE_TEXT;
1907 b_enc->subtype = mutt_str_dup("plain");
1908
1909 mutt_param_set(&b_enc->parameter, "x-action",
1910 (flags & SEC_ENCRYPT) ? "pgp-encrypted" : "pgp-signed");
1911 mutt_param_set(&b_enc->parameter, "charset", send_charset);
1912
1913 b_enc->filename = buf_strdup(pgpoutfile);
1914
1915 b_enc->disposition = DISP_NONE;
1916 b_enc->unlink = true;
1917
1918 b_enc->noconv = true;
1919 b_enc->use_disp = false;
1920
1921 if (!(flags & SEC_ENCRYPT))
1922 b_enc->encoding = b->encoding;
1923
1924cleanup:
1925 buf_pool_release(&pgpinfile);
1926 buf_pool_release(&pgpoutfile);
1927 return b_enc;
1928}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:99
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
const char * cc_charset(void)
Get the cached value of $charset.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
struct Body * mutt_body_new(void)
Create a new Body.
Definition body.c:44
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition body.c:134
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
void pgp_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition pgp.c:71
#define mutt_perror(...)
Definition logging2.h:95
@ 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
@ MODULE_ID_NCRYPT
ModuleNcrypt, Ncrypt
Definition module_api.h:82
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file's character set.
Definition charset.c:968
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:921
void mutt_ch_fgetconv_close(struct FgetConv **ptr)
Close an fgetconv handle.
Definition charset.c:950
#define MUTT_ICONV_NONE
No flags are set.
Definition charset.h:66
#define mutt_ch_is_us_ascii(str)
Definition charset.h:108
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:231
#define _(a)
Definition message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
@ SEC_SIGN
Email is signed.
Definition lib.h:93
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition parameter.c:111
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition pgp.c:124
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:264
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
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:68
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
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:61
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:59
String manipulation buffer.
Definition buffer.h:37
Cursor for converting a file's encoding.
Definition charset.h:45
Ncrypt private Module data.
Definition module_data.h:39
char pgp_pass[1024]
Cached PGP Passphrase.
Definition module_data.h:51
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
#define buf_mktemp(buf)
Definition tmp.h:33
#define mutt_file_mkstemp()
Definition tmp.h:36
Here is the call graph for this function: