NeoMutt  2022-04-29-81-g9c5a59
Teaching an old dog new tricks
DOXYGEN
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 **cur)
 Implements CryptModuleSpecs::decrypt_mime() -. More...
 
int smime_gpgme_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() -. More...
 
int pgp_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() -. More...
 
int smime_class_decrypt_mime (FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 Implements CryptModuleSpecs::decrypt_mime() -. More...
 

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]curBody 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 **  cur 
)

Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 2210 of file crypt_gpgme.c.

2211 {
2212  struct State s = { 0 };
2213  struct Body *first_part = b;
2214  int is_signed = 0;
2215  bool need_decode = false;
2216  LOFF_T saved_offset = 0;
2217  size_t saved_length = 0;
2218  FILE *fp_decoded = NULL;
2219  int rc = 0;
2220 
2221  first_part->goodsig = false;
2222  first_part->warnsig = false;
2223 
2225  {
2226  b = b->parts->next;
2227  /* Some clients improperly encode the octetstream part. */
2228  if (b->encoding != ENC_7BIT)
2229  need_decode = true;
2230  }
2232  {
2233  b = b->parts->next->next;
2234  need_decode = true;
2235  }
2236  else
2237  return -1;
2238 
2239  s.fp_in = fp_in;
2240 
2241  if (need_decode)
2242  {
2243  saved_offset = b->offset;
2244  saved_length = b->length;
2245 
2246  fp_decoded = mutt_file_mkstemp();
2247  if (!fp_decoded)
2248  {
2249  mutt_perror(_("Can't create temporary file"));
2250  return -1;
2251  }
2252 
2253  if (!mutt_file_seek(s.fp_in, b->offset, SEEK_SET))
2254  {
2255  rc = -1;
2256  goto bail;
2257  }
2258  s.fp_out = fp_decoded;
2259 
2260  mutt_decode_attachment(b, &s);
2261 
2262  fflush(fp_decoded);
2263  b->length = ftello(fp_decoded);
2264  b->offset = 0;
2265  rewind(fp_decoded);
2266  s.fp_in = fp_decoded;
2267  s.fp_out = 0;
2268  }
2269 
2270  *fp_out = mutt_file_mkstemp();
2271  if (!*fp_out)
2272  {
2273  mutt_perror(_("Can't create temporary file"));
2274  rc = -1;
2275  goto bail;
2276  }
2277 
2278  *cur = decrypt_part(b, &s, *fp_out, false, &is_signed);
2279  if (*cur)
2280  {
2281  rewind(*fp_out);
2282  if (is_signed > 0)
2283  first_part->goodsig = true;
2284  }
2285  else
2286  {
2287  rc = -1;
2288  mutt_file_fclose(fp_out);
2289  }
2290 
2291 bail:
2292  if (need_decode)
2293  {
2294  b->length = saved_length;
2295  b->offset = saved_offset;
2296  mutt_file_fclose(&fp_decoded);
2297  }
2298 
2299  return rc;
2300 }
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:463
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:500
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:2052
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define mutt_file_mkstemp()
Definition: file.h:112
#define mutt_perror(...)
Definition: logging.h:88
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email's attachment.
Definition: handler.c:1867
@ ENC_7BIT
7-bit text
Definition: mime.h:49
#define _(a)
Definition: message.h:28
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
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:71
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:46
FILE * fp_out
File to write to.
Definition: state.h:48
FILE * fp_in
File to read from.
Definition: state.h:47
+ 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 **  cur 
)

Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 2305 of file crypt_gpgme.c.

2306 {
2307  struct State s = { 0 };
2308  int is_signed;
2309  LOFF_T saved_b_offset;
2310  size_t saved_b_length;
2311 
2313  return -1;
2314 
2315  if (b->parts)
2316  return -1;
2317 
2318  /* Decode the body - we need to pass binary CMS to the
2319  * backend. The backend allows for Base64 encoded data but it does
2320  * not allow for QP which I have seen in some messages. So better
2321  * do it here. */
2322  saved_b_offset = b->offset;
2323  saved_b_length = b->length;
2324  s.fp_in = fp_in;
2325  if (!mutt_file_seek(s.fp_in, b->offset, SEEK_SET))
2326  {
2327  return -1;
2328  }
2329  FILE *fp_tmp = mutt_file_mkstemp();
2330  if (!fp_tmp)
2331  {
2332  mutt_perror(_("Can't create temporary file"));
2333  return -1;
2334  }
2335 
2336  s.fp_out = fp_tmp;
2337  mutt_decode_attachment(b, &s);
2338  fflush(fp_tmp);
2339  b->length = ftello(s.fp_out);
2340  b->offset = 0;
2341  rewind(fp_tmp);
2342 
2343  memset(&s, 0, sizeof(s));
2344  s.fp_in = fp_tmp;
2345  s.fp_out = 0;
2347  if (!*fp_out)
2348  {
2349  mutt_perror(_("Can't create temporary file"));
2350  return -1;
2351  }
2352 
2353  *cur = decrypt_part(b, &s, *fp_out, true, &is_signed);
2354  if (*cur)
2355  (*cur)->goodsig = is_signed > 0;
2356  b->length = saved_b_length;
2357  b->offset = saved_b_offset;
2358  mutt_file_fclose(&fp_tmp);
2359  rewind(*fp_out);
2360  if (*cur && !is_signed && !(*cur)->parts && mutt_is_application_smime(*cur))
2361  {
2362  /* Assume that this is a opaque signed s/mime message. This is an ugly way
2363  * of doing it but we have anyway a problem with arbitrary encoded S/MIME
2364  * messages: Only the outer part may be encrypted. The entire mime parsing
2365  * should be revamped, probably by keeping the temporary files so that we
2366  * don't need to decrypt them all the time. Inner parts of an encrypted
2367  * part can then point into this file and there won't ever be a need to
2368  * decrypt again. This needs a partial rewrite of the MIME engine. */
2369  struct Body *bb = *cur;
2370 
2371  saved_b_offset = bb->offset;
2372  saved_b_length = bb->length;
2373  memset(&s, 0, sizeof(s));
2374  s.fp_in = *fp_out;
2375  if (!mutt_file_seek(s.fp_in, bb->offset, SEEK_SET))
2376  {
2377  return -1;
2378  }
2379  FILE *fp_tmp2 = mutt_file_mkstemp();
2380  if (!fp_tmp2)
2381  {
2382  mutt_perror(_("Can't create temporary file"));
2383  return -1;
2384  }
2385 
2386  s.fp_out = fp_tmp2;
2387  mutt_decode_attachment(bb, &s);
2388  fflush(fp_tmp2);
2389  bb->length = ftello(s.fp_out);
2390  bb->offset = 0;
2391  rewind(fp_tmp2);
2392  mutt_file_fclose(fp_out);
2393 
2394  memset(&s, 0, sizeof(s));
2395  s.fp_in = fp_tmp2;
2396  s.fp_out = 0;
2397  *fp_out = mutt_file_mkstemp();
2398  if (!*fp_out)
2399  {
2400  mutt_perror(_("Can't create temporary file"));
2401  return -1;
2402  }
2403 
2404  struct Body *b_tmp = decrypt_part(bb, &s, *fp_out, true, &is_signed);
2405  if (b_tmp)
2406  b_tmp->goodsig = is_signed > 0;
2407  bb->length = saved_b_length;
2408  bb->offset = saved_b_offset;
2409  mutt_file_fclose(&fp_tmp2);
2410  rewind(*fp_out);
2411  mutt_body_free(cur);
2412  *cur = b_tmp;
2413  }
2414  return *cur ? 0 : -1;
2415 }
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:77
+ 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 **  cur 
)

Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 1141 of file pgp.c.

1142 {
1143  struct State s = { 0 };
1144  struct Body *p = b;
1145  bool need_decode = false;
1146  LOFF_T saved_offset = 0;
1147  size_t saved_length = 0;
1148  FILE *fp_decoded = NULL;
1149  int rc = 0;
1150 
1152  {
1153  b = b->parts->next;
1154  /* Some clients improperly encode the octetstream part. */
1155  if (b->encoding != ENC_7BIT)
1156  need_decode = true;
1157  }
1159  {
1160  b = b->parts->next->next;
1161  need_decode = true;
1162  }
1163  else
1164  return -1;
1165 
1166  s.fp_in = fp_in;
1167 
1168  if (need_decode)
1169  {
1170  saved_offset = b->offset;
1171  saved_length = b->length;
1172 
1173  fp_decoded = mutt_file_mkstemp();
1174  if (!fp_decoded)
1175  {
1176  mutt_perror(_("Can't create temporary file"));
1177  return -1;
1178  }
1179 
1180  if (!mutt_file_seek(s.fp_in, b->offset, SEEK_SET))
1181  {
1182  rc = -1;
1183  goto bail;
1184  }
1185  s.fp_out = fp_decoded;
1186 
1187  mutt_decode_attachment(b, &s);
1188 
1189  fflush(fp_decoded);
1190  b->length = ftello(fp_decoded);
1191  b->offset = 0;
1192  rewind(fp_decoded);
1193  s.fp_in = fp_decoded;
1194  s.fp_out = 0;
1195  }
1196 
1197  *fp_out = mutt_file_mkstemp();
1198  if (!*fp_out)
1199  {
1200  mutt_perror(_("Can't create temporary file"));
1201  rc = -1;
1202  goto bail;
1203  }
1204 
1205  *cur = pgp_decrypt_part(b, &s, *fp_out, p);
1206  if (!*cur)
1207  rc = -1;
1208  rewind(*fp_out);
1209 
1210 bail:
1211  if (need_decode)
1212  {
1213  b->length = saved_length;
1214  b->offset = saved_offset;
1215  mutt_file_fclose(&fp_decoded);
1216  }
1217 
1218  return rc;
1219 }
static struct Body * pgp_decrypt_part(struct Body *a, struct State *s, FILE *fp_out, struct Body *p)
Decrypt part of a PGP message.
Definition: pgp.c:1005
+ 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 **  cur 
)

Implements CryptModuleSpecs::decrypt_mime() -.

Definition at line 2072 of file smime.c.

2073 {
2074  struct State s = { 0 };
2075  LOFF_T tmpoffset = b->offset;
2076  size_t tmplength = b->length;
2077  int rc = -1;
2078 
2079  if (!mutt_is_application_smime(b))
2080  return -1;
2081 
2082  if (b->parts)
2083  return -1;
2084 
2085  s.fp_in = fp_in;
2086  if (!mutt_file_seek(s.fp_in, b->offset, SEEK_SET))
2087  {
2088  return -1;
2089  }
2090 
2091  FILE *fp_tmp = mutt_file_mkstemp();
2092  if (!fp_tmp)
2093  {
2094  mutt_perror(_("Can't create temporary file"));
2095  return -1;
2096  }
2097 
2098  s.fp_out = fp_tmp;
2099  mutt_decode_attachment(b, &s);
2100  fflush(fp_tmp);
2101  b->length = ftello(s.fp_out);
2102  b->offset = 0;
2103  rewind(fp_tmp);
2104  s.fp_in = fp_tmp;
2105  s.fp_out = 0;
2106 
2108  if (!*fp_out)
2109  {
2110  mutt_perror(_("Can't create temporary file"));
2111  goto bail;
2112  }
2113 
2114  *cur = smime_handle_entity(b, &s, *fp_out);
2115  if (!*cur)
2116  goto bail;
2117 
2118  (*cur)->goodsig = b->goodsig;
2119  (*cur)->badsig = b->badsig;
2120  rc = 0;
2121 
2122 bail:
2123  b->length = tmplength;
2124  b->offset = tmpoffset;
2125  mutt_file_fclose(&fp_tmp);
2126  if (*fp_out)
2127  rewind(*fp_out);
2128 
2129  return rc;
2130 }
static struct Body * smime_handle_entity(struct Body *m, struct State *s, FILE *fp_out_file)
Handle type application/pkcs7-mime.
Definition: smime.c:1837
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:43
+ Here is the call graph for this function: