NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
smime_build_smime_entity()

Encrypt the email body to all recipients. More...

+ Collaboration diagram for smime_build_smime_entity():

Functions

struct Bodysmime_gpgme_build_smime_entity (struct Body *a, char *keylist)
 Implements CryptModuleSpecs::smime_build_smime_entity() -. More...
 
struct Bodysmime_class_build_smime_entity (struct Body *a, char *certlist)
 Implements CryptModuleSpecs::smime_build_smime_entity() -. More...
 

Detailed Description

Encrypt the email body to all recipients.

Parameters
aBody of email
certlistList of key fingerprints (space separated)
Return values
ptrNew S/MIME encrypted Body
NULLError

Function Documentation

◆ smime_gpgme_build_smime_entity()

struct Body* smime_gpgme_build_smime_entity ( struct Body a,
char *  keylist 
)

Implements CryptModuleSpecs::smime_build_smime_entity() -.

Definition at line 1446 of file crypt_gpgme.c.

1447 {
1448  /* OpenSSL converts line endings to crlf when encrypting. Some clients
1449  * depend on this for signed+encrypted messages: they do not convert line
1450  * endings between decrypting and checking the signature. */
1451  gpgme_data_t plaintext = body_to_data_object(a, true);
1452  if (!plaintext)
1453  return NULL;
1454 
1455  char *outfile = encrypt_gpgme_object(plaintext, keylist, true, false, NULL);
1456  gpgme_data_release(plaintext);
1457  if (!outfile)
1458  return NULL;
1459 
1460  struct Body *t = mutt_body_new();
1461  t->type = TYPE_APPLICATION;
1462  t->subtype = mutt_str_dup("pkcs7-mime");
1463  mutt_param_set(&t->parameter, "name", "smime.p7m");
1464  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1465  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1466  t->use_disp = true;
1467  t->disposition = DISP_ATTACH;
1468  t->d_filename = mutt_str_dup("smime.p7m");
1469  t->filename = outfile;
1470  t->unlink = true; /* delete after sending the message */
1471  t->parts = 0;
1472  t->next = 0;
1473 
1474  return t;
1475 }
static gpgme_data_t body_to_data_object(struct Body *a, bool convert)
Create GPGME object from the mail body.
Definition: crypt_gpgme.c:677
static char * encrypt_gpgme_object(gpgme_data_t plaintext, char *keylist, bool use_smime, bool combined_signed, const struct AddressList *from)
Encrypt the GPGPME data object.
Definition: crypt_gpgme.c:1120
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
@ ENC_BASE64
Base-64 encoded text.
Definition: mime.h:52
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
@ DISP_ATTACH
Content is attached.
Definition: mime.h:63
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
The body of an email.
Definition: body.h:36
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
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
struct Body * next
next attachment in the list
Definition: body.h:71
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
+ Here is the call graph for this function:

◆ smime_class_build_smime_entity()

struct Body* smime_class_build_smime_entity ( struct Body a,
char *  certlist 
)

Implements CryptModuleSpecs::smime_build_smime_entity() -.

Definition at line 1353 of file smime.c.

1354 {
1355  char buf[1024], certfile[PATH_MAX];
1356  char *cert_end = NULL;
1357  FILE *fp_smime_in = NULL, *fp_smime_err = NULL, *fp_out = NULL, *fp_tmp = NULL;
1358  struct Body *t = NULL;
1359  int err = 0, empty, off;
1360  pid_t pid;
1361 
1362  struct Buffer *tempfile = mutt_buffer_pool_get();
1363  struct Buffer *smime_infile = mutt_buffer_pool_get();
1364 
1365  mutt_buffer_mktemp(tempfile);
1366  fp_out = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
1367  if (!fp_out)
1368  {
1369  mutt_perror(mutt_buffer_string(tempfile));
1370  goto cleanup;
1371  }
1372 
1373  fp_smime_err = mutt_file_mkstemp();
1374  if (!fp_smime_err)
1375  {
1376  mutt_perror(_("Can't create temporary file"));
1377  goto cleanup;
1378  }
1379 
1380  mutt_buffer_mktemp(smime_infile);
1381  fp_tmp = mutt_file_fopen(mutt_buffer_string(smime_infile), "w+");
1382  if (!fp_tmp)
1383  {
1384  mutt_perror(mutt_buffer_string(smime_infile));
1385  goto cleanup;
1386  }
1387 
1388  *certfile = '\0';
1389  for (char *cert_start = certlist; cert_start; cert_start = cert_end)
1390  {
1391  cert_end = strchr(cert_start, ' ');
1392  if (cert_end)
1393  *cert_end = '\0';
1394  if (*cert_start)
1395  {
1396  off = mutt_str_len(certfile);
1397  const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
1398  snprintf(certfile + off, sizeof(certfile) - off, "%s%s/%s",
1399  (off != 0) ? " " : "", NONULL(c_smime_certificates), cert_start);
1400  }
1401  if (cert_end)
1402  *cert_end++ = ' ';
1403  }
1404 
1405  /* write a MIME entity */
1406  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
1407  fputc('\n', fp_tmp);
1408  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
1409  mutt_file_fclose(&fp_tmp);
1410 
1411  pid = smime_invoke_encrypt(&fp_smime_in, NULL, NULL, -1, fileno(fp_out),
1412  fileno(fp_smime_err),
1413  mutt_buffer_string(smime_infile), certfile);
1414  if (pid == -1)
1415  {
1416  mutt_file_unlink(mutt_buffer_string(smime_infile));
1417  goto cleanup;
1418  }
1419 
1420  mutt_file_fclose(&fp_smime_in);
1421 
1422  filter_wait(pid);
1423  mutt_file_unlink(mutt_buffer_string(smime_infile));
1424 
1425  fflush(fp_out);
1426  rewind(fp_out);
1427  empty = (fgetc(fp_out) == EOF);
1428  mutt_file_fclose(&fp_out);
1429 
1430  fflush(fp_smime_err);
1431  rewind(fp_smime_err);
1432  while (fgets(buf, sizeof(buf) - 1, fp_smime_err))
1433  {
1434  err = 1;
1435  fputs(buf, stdout);
1436  }
1437  mutt_file_fclose(&fp_smime_err);
1438 
1439  /* pause if there is any error output from SMIME */
1440  if (err)
1442 
1443  if (empty)
1444  {
1445  /* fatal error while trying to encrypt message */
1446  if (err == 0)
1447  mutt_any_key_to_continue(_("No output from OpenSSL..."));
1449  goto cleanup;
1450  }
1451 
1452  t = mutt_body_new();
1453  t->type = TYPE_APPLICATION;
1454  t->subtype = mutt_str_dup("x-pkcs7-mime");
1455  mutt_param_set(&t->parameter, "name", "smime.p7m");
1456  mutt_param_set(&t->parameter, "smime-type", "enveloped-data");
1457  t->encoding = ENC_BASE64; /* The output of OpenSSL SHOULD be binary */
1458  t->use_disp = true;
1459  t->disposition = DISP_ATTACH;
1460  t->d_filename = mutt_str_dup("smime.p7m");
1461  t->filename = mutt_buffer_strdup(tempfile);
1462  t->unlink = true; /* delete after sending the message */
1463  t->parts = NULL;
1464  t->next = NULL;
1465 
1466 cleanup:
1467  if (fp_out)
1468  {
1469  mutt_file_fclose(&fp_out);
1471  }
1472  mutt_file_fclose(&fp_smime_err);
1473  if (fp_tmp)
1474  {
1475  mutt_file_fclose(&fp_tmp);
1476  mutt_file_unlink(mutt_buffer_string(smime_infile));
1477  }
1478  mutt_buffer_pool_release(&tempfile);
1479  mutt_buffer_pool_release(&smime_infile);
1480 
1481  return t;
1482 }
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:430
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
#define mutt_file_mkstemp()
Definition: file.h:112
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
#define mutt_perror(...)
Definition: logging.h:88
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
#define _(a)
Definition: message.h:28
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
#define PATH_MAX
Definition: mutt.h:40
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
static pid_t smime_invoke_encrypt(FILE **fp_smime_in, FILE **fp_smime_out, FILE **fp_smime_err, int fp_smime_infd, int fp_smime_outfd, int fp_smime_errfd, const char *fname, const char *uids)
Use SMIME to encrypt a file.
Definition: smime.c:1310
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function: