NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
decrypt_mime()

Decrypt an encrypted MIME part. More...

Collaboration diagram for decrypt_mime():

Functions

int pgp_gpgme_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
 Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.
int smime_gpgme_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
 Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.
int pgp_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
 Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.
int smime_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
 Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.

Detailed Description

Decrypt an encrypted MIME part.

Parameters
[in]fp_inFile containing the encrypted part
[out]fp_outFile containing the decrypted part
[in]bBody of the email
[out]b_decBody containing the decrypted part
Return values
0Success
-1Failure

Function Documentation

◆ pgp_gpgme_decrypt_mime()

int pgp_gpgme_decrypt_mime ( FILE * fp_in,
FILE ** fp_out,
struct Body * b,
struct Body ** b_dec )

Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 1915 of file crypt_gpgme.c.

1916{
1917 struct State state = { 0 };
1918 struct Body *first_part = b;
1919 int is_signed = 0;
1920 bool need_decode = false;
1921 LOFF_T saved_offset = 0;
1922 size_t saved_length = 0;
1923 FILE *fp_decoded = NULL;
1924 int rc = 0;
1925
1926 first_part->goodsig = false;
1927 first_part->warnsig = false;
1928
1930 {
1931 b = b->parts->next;
1932 /* Some clients improperly encode the octetstream part. */
1933 if (b->encoding != ENC_7BIT)
1934 need_decode = true;
1935 }
1937 {
1938 b = b->parts->next->next;
1939 need_decode = true;
1940 }
1941 else
1942 {
1943 return -1;
1944 }
1945
1946 state.fp_in = fp_in;
1947
1948 if (need_decode)
1949 {
1950 saved_offset = b->offset;
1951 saved_length = b->length;
1952
1953 fp_decoded = mutt_file_mkstemp();
1954 if (!fp_decoded)
1955 {
1956 mutt_perror(_("Can't create temporary file"));
1957 return -1;
1958 }
1959
1960 if (!mutt_file_seek(state.fp_in, b->offset, SEEK_SET))
1961 {
1962 rc = -1;
1963 goto bail;
1964 }
1965 state.fp_out = fp_decoded;
1966
1967 mutt_decode_attachment(b, &state);
1968
1969 fflush(fp_decoded);
1970 b->length = ftello(fp_decoded);
1971 b->offset = 0;
1972 fseek(fp_decoded, 0, SEEK_SET);
1973 clearerr(fp_decoded);
1974 state.fp_in = fp_decoded;
1975 state.fp_out = 0;
1976 }
1977
1978 *fp_out = mutt_file_mkstemp();
1979 if (!*fp_out)
1980 {
1981 mutt_perror(_("Can't create temporary file"));
1982 rc = -1;
1983 goto bail;
1984 }
1985
1986 *b_dec = decrypt_part(b, &state, *fp_out, false, &is_signed);
1987 if (*b_dec)
1988 {
1989 fseek(*fp_out, 0, SEEK_SET);
1990 clearerr(*fp_out);
1991 if (is_signed > 0)
1992 first_part->goodsig = true;
1993 }
1994 else
1995 {
1996 rc = -1;
1997 mutt_file_fclose(fp_out);
1998 }
1999
2000bail:
2001 if (need_decode)
2002 {
2003 b->length = saved_length;
2004 b->offset = saved_offset;
2005 mutt_file_fclose(&fp_decoded);
2006 }
2007
2008 return rc;
2009}
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition crypt.c:468
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition crypt.c:505
static struct Body * decrypt_part(struct Body *b, struct State *state, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_perror(...)
Definition logging2.h:95
void mutt_decode_attachment(const struct Body *b, struct State *state)
Decode an email's attachment.
Definition handler.c:1950
@ ENC_7BIT
7-bit text
Definition mime.h:49
#define _(a)
Definition message.h:28
#define PGP_ENCRYPT
Email is PGP encrypted.
Definition lib.h:112
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
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
struct Body * next
next attachment in the list
Definition body.h:72
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition body.h:41
bool goodsig
Good cryptographic signature.
Definition body.h:45
bool warnsig
Maybe good signature.
Definition body.h:48
Keep track when processing files.
Definition state.h:54
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
#define mutt_file_mkstemp()
Definition tmp.h:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ smime_gpgme_decrypt_mime()

int smime_gpgme_decrypt_mime ( FILE * fp_in,
FILE ** fp_out,
struct Body * b,
struct Body ** b_dec )

Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 2014 of file crypt_gpgme.c.

2015{
2016 struct State state = { 0 };
2017 int is_signed = 0;
2018 LOFF_T saved_b_offset;
2019 size_t saved_b_length;
2020
2022 return -1;
2023
2024 if (b->parts)
2025 return -1;
2026
2027 /* Decode the body - we need to pass binary CMS to the
2028 * backend. The backend allows for Base64 encoded data but it does
2029 * not allow for QP which I have seen in some messages. So better
2030 * do it here. */
2031 saved_b_offset = b->offset;
2032 saved_b_length = b->length;
2033 state.fp_in = fp_in;
2034 if (!mutt_file_seek(state.fp_in, b->offset, SEEK_SET))
2035 {
2036 return -1;
2037 }
2038 FILE *fp_tmp = mutt_file_mkstemp();
2039 if (!fp_tmp)
2040 {
2041 mutt_perror(_("Can't create temporary file"));
2042 return -1;
2043 }
2044
2045 state.fp_out = fp_tmp;
2046 mutt_decode_attachment(b, &state);
2047 fflush(fp_tmp);
2048 b->length = ftello(state.fp_out);
2049 b->offset = 0;
2050 fseek(fp_tmp, 0, SEEK_SET);
2051 clearerr(fp_tmp);
2052
2053 memset(&state, 0, sizeof(state));
2054 state.fp_in = fp_tmp;
2055 state.fp_out = 0;
2057 if (!*fp_out)
2058 {
2059 mutt_perror(_("Can't create temporary file"));
2060 mutt_file_fclose(&fp_tmp);
2061 return -1;
2062 }
2063
2064 *b_dec = decrypt_part(b, &state, *fp_out, true, &is_signed);
2065 if (*b_dec)
2066 (*b_dec)->goodsig = is_signed > 0;
2067 b->length = saved_b_length;
2068 b->offset = saved_b_offset;
2069 mutt_file_fclose(&fp_tmp);
2070 fseek(*fp_out, 0, SEEK_SET);
2071 clearerr(*fp_out);
2072 if (*b_dec && !is_signed && !(*b_dec)->parts && mutt_is_application_smime(*b_dec))
2073 {
2074 /* Assume that this is a opaque signed s/mime message. This is an ugly way
2075 * of doing it but we have anyway a problem with arbitrary encoded S/MIME
2076 * messages: Only the outer part may be encrypted. The entire mime parsing
2077 * should be revamped, probably by keeping the temporary files so that we
2078 * don't need to decrypt them all the time. Inner parts of an encrypted
2079 * part can then point into this file and there won't ever be a need to
2080 * decrypt again. This needs a partial rewrite of the MIME engine. */
2081 struct Body *bb = *b_dec;
2082
2083 saved_b_offset = bb->offset;
2084 saved_b_length = bb->length;
2085 memset(&state, 0, sizeof(state));
2086 state.fp_in = *fp_out;
2087 if (!mutt_file_seek(state.fp_in, bb->offset, SEEK_SET))
2088 {
2089 return -1;
2090 }
2091 FILE *fp_tmp2 = mutt_file_mkstemp();
2092 if (!fp_tmp2)
2093 {
2094 mutt_perror(_("Can't create temporary file"));
2095 return -1;
2096 }
2097
2098 state.fp_out = fp_tmp2;
2099 mutt_decode_attachment(bb, &state);
2100 fflush(fp_tmp2);
2101 bb->length = ftello(state.fp_out);
2102 bb->offset = 0;
2103 fseek(fp_tmp2, 0, SEEK_SET);
2104 clearerr(fp_tmp2);
2105 mutt_file_fclose(fp_out);
2106
2107 memset(&state, 0, sizeof(state));
2108 state.fp_in = fp_tmp2;
2109 state.fp_out = 0;
2110 *fp_out = mutt_file_mkstemp();
2111 if (!*fp_out)
2112 {
2113 mutt_perror(_("Can't create temporary file"));
2114 mutt_file_fclose(&fp_tmp2);
2115 return -1;
2116 }
2117
2118 struct Body *b_tmp = decrypt_part(bb, &state, *fp_out, true, &is_signed);
2119 if (b_tmp)
2120 b_tmp->goodsig = is_signed > 0;
2121 bb->length = saved_b_length;
2122 bb->offset = saved_b_offset;
2123 mutt_file_fclose(&fp_tmp2);
2124 fseek(*fp_out, 0, SEEK_SET);
2125 clearerr(*fp_out);
2126 mutt_body_free(b_dec);
2127 *b_dec = b_tmp;
2128 }
2129 return *b_dec ? 0 : -1;
2130}
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:610
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
@ SEC_NONE
No flags are set.
Definition lib.h:91
Here is the call graph for this function:

◆ pgp_class_decrypt_mime()

int pgp_class_decrypt_mime ( FILE * fp_in,
FILE ** fp_out,
struct Body * b,
struct Body ** b_dec )

Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 1177 of file pgp.c.

1178{
1179 struct State state = { 0 };
1180 struct Body *p = b;
1181 bool need_decode = false;
1182 LOFF_T saved_offset = 0;
1183 size_t saved_length = 0;
1184 FILE *fp_decoded = NULL;
1185 int rc = 0;
1186
1188 {
1189 b = b->parts->next;
1190 /* Some clients improperly encode the octetstream part. */
1191 if (b->encoding != ENC_7BIT)
1192 need_decode = true;
1193 }
1195 {
1196 b = b->parts->next->next;
1197 need_decode = true;
1198 }
1199 else
1200 {
1201 return -1;
1202 }
1203
1204 state.fp_in = fp_in;
1205
1206 if (need_decode)
1207 {
1208 saved_offset = b->offset;
1209 saved_length = b->length;
1210
1211 fp_decoded = mutt_file_mkstemp();
1212 if (!fp_decoded)
1213 {
1214 mutt_perror(_("Can't create temporary file"));
1215 return -1;
1216 }
1217
1218 if (!mutt_file_seek(state.fp_in, b->offset, SEEK_SET))
1219 {
1220 rc = -1;
1221 goto bail;
1222 }
1223 state.fp_out = fp_decoded;
1224
1225 mutt_decode_attachment(b, &state);
1226
1227 fflush(fp_decoded);
1228 b->length = ftello(fp_decoded);
1229 b->offset = 0;
1230 fseek(fp_decoded, 0, SEEK_SET);
1231 clearerr(fp_decoded);
1232 state.fp_in = fp_decoded;
1233 state.fp_out = 0;
1234 }
1235
1236 *fp_out = mutt_file_mkstemp();
1237 if (!*fp_out)
1238 {
1239 mutt_perror(_("Can't create temporary file"));
1240 rc = -1;
1241 goto bail;
1242 }
1243
1244 *b_dec = pgp_decrypt_part(b, &state, *fp_out, p);
1245 if (!*b_dec)
1246 rc = -1;
1247 fseek(*fp_out, 0, SEEK_SET);
1248 clearerr(*fp_out);
1249
1250bail:
1251 if (need_decode)
1252 {
1253 b->length = saved_length;
1254 b->offset = saved_offset;
1255 mutt_file_fclose(&fp_decoded);
1256 }
1257
1258 return rc;
1259}
static struct Body * pgp_decrypt_part(struct Body *a, struct State *state, FILE *fp_out, struct Body *p)
Decrypt part of a PGP message.
Definition pgp.c:1034
Here is the call graph for this function:

◆ smime_class_decrypt_mime()

int smime_class_decrypt_mime ( FILE * fp_in,
FILE ** fp_out,
struct Body * b,
struct Body ** b_dec )

Decrypt an encrypted MIME part - Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 1972 of file smime.c.

1973{
1974 struct State state = { 0 };
1975 LOFF_T tmpoffset = b->offset;
1976 size_t tmplength = b->length;
1977 int rc = -1;
1978
1980 return -1;
1981
1982 if (b->parts)
1983 return -1;
1984
1985 state.fp_in = fp_in;
1986 if (!mutt_file_seek(state.fp_in, b->offset, SEEK_SET))
1987 {
1988 return -1;
1989 }
1990
1991 FILE *fp_tmp = mutt_file_mkstemp();
1992 if (!fp_tmp)
1993 {
1994 mutt_perror(_("Can't create temporary file"));
1995 return -1;
1996 }
1997
1998 state.fp_out = fp_tmp;
1999 mutt_decode_attachment(b, &state);
2000 fflush(fp_tmp);
2001 b->length = ftello(state.fp_out);
2002 b->offset = 0;
2003 fseek(fp_tmp, 0, SEEK_SET);
2004 clearerr(fp_tmp);
2005 state.fp_in = fp_tmp;
2006 state.fp_out = 0;
2007
2009 if (!*fp_out)
2010 {
2011 mutt_perror(_("Can't create temporary file"));
2012 goto bail;
2013 }
2014
2015 *b_dec = smime_handle_entity(b, &state, *fp_out);
2016 if (!*b_dec)
2017 goto bail;
2018
2019 (*b_dec)->goodsig = b->goodsig;
2020 (*b_dec)->badsig = b->badsig;
2021 rc = 0;
2022
2023bail:
2024 b->length = tmplength;
2025 b->offset = tmpoffset;
2026 mutt_file_fclose(&fp_tmp);
2027 if (*fp_out)
2028 {
2029 fseek(*fp_out, 0, SEEK_SET);
2030 clearerr(*fp_out);
2031 }
2032
2033 return rc;
2034}
static struct Body * smime_handle_entity(struct Body *b, struct State *state, FILE *fp_out_file)
Handle type application/pkcs7-mime.
Definition smime.c:1724
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures).
Definition body.h:43
Here is the call graph for this function: