NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
sign_message()

Cryptographically sign the Body of a message. More...

+ Collaboration diagram for sign_message():

Functions

struct Bodypgp_gpgme_sign_message (struct Body *b, const struct AddressList *from)
 Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.
 
struct Bodysmime_gpgme_sign_message (struct Body *b, const struct AddressList *from)
 Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.
 
struct Bodypgp_class_sign_message (struct Body *b, const struct AddressList *from)
 Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.
 
struct Bodysmime_class_sign_message (struct Body *b, const struct AddressList *from)
 Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.
 

Detailed Description

Cryptographically sign the Body of a message.

Parameters
bBody of the message
fromFrom line
Return values
ptrNew encrypted Body
NULLError

Function Documentation

◆ pgp_gpgme_sign_message()

struct Body * pgp_gpgme_sign_message ( struct Body b,
const struct AddressList *  from 
)

Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.

Definition at line 1027 of file crypt_gpgme.c.

1028{
1029 return sign_message(b, from, false);
1030}
static struct Body * sign_message(struct Body *b, const struct AddressList *from, bool use_smime)
Sign a message.
Definition: crypt_gpgme.c:906
+ Here is the call graph for this function:

◆ smime_gpgme_sign_message()

struct Body * smime_gpgme_sign_message ( struct Body b,
const struct AddressList *  from 
)

Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.

Definition at line 1035 of file crypt_gpgme.c.

1036{
1037 return sign_message(b, from, true);
1038}
+ Here is the call graph for this function:

◆ pgp_class_sign_message()

struct Body * pgp_class_sign_message ( struct Body b,
const struct AddressList *  from 
)

Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.

Definition at line 1335 of file pgp.c.

1336{
1337 struct Body *b_enc = NULL, *rv = NULL;
1338 char buf[1024] = { 0 };
1339 FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_err = NULL, *fp_signed = NULL;
1340 bool err = false;
1341 bool empty = true;
1342 pid_t pid;
1343 struct Buffer *sigfile = buf_pool_get();
1344 struct Buffer *signedfile = buf_pool_get();
1345
1346 crypt_convert_to_7bit(b); /* Signed data _must_ be in 7-bit format. */
1347
1348 buf_mktemp(sigfile);
1349 FILE *fp_sig = mutt_file_fopen(buf_string(sigfile), "w");
1350 if (!fp_sig)
1351 {
1352 goto cleanup;
1353 }
1354
1355 buf_mktemp(signedfile);
1356 fp_signed = mutt_file_fopen(buf_string(signedfile), "w");
1357 if (!fp_signed)
1358 {
1359 mutt_perror("%s", buf_string(signedfile));
1360 mutt_file_fclose(&fp_sig);
1361 unlink(buf_string(sigfile));
1362 goto cleanup;
1363 }
1364
1365 mutt_write_mime_header(b, fp_signed, NeoMutt->sub);
1366 fputc('\n', fp_signed);
1367 mutt_write_mime_body(b, fp_signed, NeoMutt->sub);
1368 mutt_file_fclose(&fp_signed);
1369
1370 pid = pgp_invoke_sign(&fp_pgp_in, &fp_pgp_out, &fp_pgp_err, -1, -1, -1,
1371 buf_string(signedfile));
1372 if (pid == -1)
1373 {
1374 mutt_perror(_("Can't open PGP subprocess"));
1375 mutt_file_fclose(&fp_sig);
1376 unlink(buf_string(sigfile));
1377 unlink(buf_string(signedfile));
1378 goto cleanup;
1379 }
1380
1381 if (!pgp_use_gpg_agent())
1382 fputs(PgpPass, fp_pgp_in);
1383 fputc('\n', fp_pgp_in);
1384 mutt_file_fclose(&fp_pgp_in);
1385
1386 /* Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as
1387 * recommended for future releases of PGP. */
1388 while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1389 {
1390 if (mutt_str_equal("-----BEGIN PGP MESSAGE-----\n", buf))
1391 fputs("-----BEGIN PGP SIGNATURE-----\n", fp_sig);
1392 else if (mutt_str_equal("-----END PGP MESSAGE-----\n", buf))
1393 fputs("-----END PGP SIGNATURE-----\n", fp_sig);
1394 else
1395 fputs(buf, fp_sig);
1396 empty = false; /* got some output, so we're ok */
1397 }
1398
1399 /* check for errors from PGP */
1400 err = false;
1401 while (fgets(buf, sizeof(buf) - 1, fp_pgp_err))
1402 {
1403 err = true;
1404 fputs(buf, stdout);
1405 }
1406
1407 const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1408 if (filter_wait(pid) && c_pgp_check_exit)
1409 empty = true;
1410
1411 mutt_file_fclose(&fp_pgp_err);
1412 mutt_file_fclose(&fp_pgp_out);
1413 unlink(buf_string(signedfile));
1414
1415 if (mutt_file_fclose(&fp_sig) != 0)
1416 {
1417 mutt_perror("fclose");
1418 unlink(buf_string(sigfile));
1419 goto cleanup;
1420 }
1421
1422 if (err)
1424 if (empty)
1425 {
1426 unlink(buf_string(sigfile));
1427 /* most likely error is a bad passphrase, so automatically forget it */
1429 goto cleanup; /* fatal error while signing */
1430 }
1431
1432 b_enc = mutt_body_new();
1433 b_enc->type = TYPE_MULTIPART;
1434 b_enc->subtype = mutt_str_dup("signed");
1435 b_enc->encoding = ENC_7BIT;
1436 b_enc->use_disp = false;
1437 b_enc->disposition = DISP_INLINE;
1438 rv = b_enc;
1439
1441 mutt_param_set(&b_enc->parameter, "protocol", "application/pgp-signature");
1442 mutt_param_set(&b_enc->parameter, "micalg", pgp_micalg(buf_string(sigfile)));
1443
1444 b_enc->parts = b;
1445
1446 b_enc->parts->next = mutt_body_new();
1447 b_enc = b_enc->parts->next;
1448 b_enc->type = TYPE_APPLICATION;
1449 b_enc->subtype = mutt_str_dup("pgp-signature");
1450 b_enc->filename = buf_strdup(sigfile);
1451 b_enc->use_disp = false;
1452 b_enc->disposition = DISP_NONE;
1453 b_enc->encoding = ENC_7BIT;
1454 b_enc->unlink = true; /* ok to remove this file after sending. */
1455 mutt_param_set(&b_enc->parameter, "name", "signature.asc");
1456
1457cleanup:
1458 buf_pool_release(&sigfile);
1459 buf_pool_release(&signedfile);
1460 return rv;
1461}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:570
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
void crypt_convert_to_7bit(struct Body *b)
Convert an email to 7bit encoding.
Definition: crypt.c:795
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:173
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:44
#define mutt_file_fclose(FP)
Definition: file.h:147
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:146
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
void pgp_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition: pgp.c:76
#define mutt_perror(...)
Definition: logging2.h:93
int mutt_write_mime_header(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:756
@ ENC_7BIT
7-bit text
Definition: mime.h:49
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
@ DISP_NONE
No preferred disposition.
Definition: mime.h:65
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:86
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:654
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:111
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:127
pid_t pgp_invoke_sign(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)
Use PGP to sign a file.
Definition: pgpinvoke.c:272
const char * pgp_micalg(const char *fname)
Find the hash algorithm of a file.
Definition: pgpmicalg.c:228
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
int mutt_write_mime_body(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:300
The body of an email.
Definition: body.h:36
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
String manipulation buffer.
Definition: buffer.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
#define buf_mktemp(buf)
Definition: tmp.h:33
+ Here is the call graph for this function:

◆ smime_class_sign_message()

struct Body * smime_class_sign_message ( struct Body b,
const struct AddressList *  from 
)

Cryptographically sign the Body of a message - Implements CryptModuleSpecs::sign_message() -.

Definition at line 1496 of file smime.c.

1497{
1498 struct Body *b_sign = NULL;
1499 struct Body *rc = NULL;
1500 char buf[1024] = { 0 };
1501 struct Buffer *filetosign = NULL, *signedfile = NULL;
1502 FILE *fp_smime_in = NULL, *fp_smime_out = NULL, *fp_smime_err = NULL, *fp_sign = NULL;
1503 bool err = false;
1504 int empty = 0;
1505 pid_t pid;
1506 const char *intermediates = NULL;
1507
1508 const char *const c_smime_sign_as = cs_subset_string(NeoMutt->sub, "smime_sign_as");
1509 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
1510 const char *signas = c_smime_sign_as ? c_smime_sign_as : c_smime_default_key;
1511 if (!signas || (*signas == '\0'))
1512 {
1513 mutt_error(_("Can't sign: No key specified. Use Sign As."));
1514 return NULL;
1515 }
1516
1517 crypt_convert_to_7bit(b); /* Signed data _must_ be in 7-bit format. */
1518
1519 filetosign = buf_pool_get();
1520 signedfile = buf_pool_get();
1521
1522 buf_mktemp(filetosign);
1523 fp_sign = mutt_file_fopen(buf_string(filetosign), "w+");
1524 if (!fp_sign)
1525 {
1526 mutt_perror("%s", buf_string(filetosign));
1527 goto cleanup;
1528 }
1529
1530 buf_mktemp(signedfile);
1531 fp_smime_out = mutt_file_fopen(buf_string(signedfile), "w+");
1532 if (!fp_smime_out)
1533 {
1534 mutt_perror("%s", buf_string(signedfile));
1535 goto cleanup;
1536 }
1537
1538 mutt_write_mime_header(b, fp_sign, NeoMutt->sub);
1539 fputc('\n', fp_sign);
1540 mutt_write_mime_body(b, fp_sign, NeoMutt->sub);
1541 mutt_file_fclose(&fp_sign);
1542
1543 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
1544 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
1545 buf_printf(&SmimeKeyToUse, "%s/%s", NONULL(c_smime_keys), signas);
1546 buf_printf(&SmimeCertToUse, "%s/%s", NONULL(c_smime_certificates), signas);
1547
1548 struct SmimeKey *signas_key = smime_get_key_by_hash(signas, 1);
1549 if (!signas_key || mutt_str_equal("?", signas_key->issuer))
1550 intermediates = signas; /* so openssl won't complain in any case */
1551 else
1552 intermediates = signas_key->issuer;
1553
1554 buf_printf(&SmimeIntermediateToUse, "%s/%s", NONULL(c_smime_certificates), intermediates);
1555
1556 smime_key_free(&signas_key);
1557
1558 pid = smime_invoke_sign(&fp_smime_in, NULL, &fp_smime_err, -1,
1559 fileno(fp_smime_out), -1, buf_string(filetosign));
1560 if (pid == -1)
1561 {
1562 mutt_perror(_("Can't open OpenSSL subprocess"));
1563 mutt_file_unlink(buf_string(filetosign));
1564 goto cleanup;
1565 }
1566 fputs(SmimePass, fp_smime_in);
1567 fputc('\n', fp_smime_in);
1568 mutt_file_fclose(&fp_smime_in);
1569
1570 filter_wait(pid);
1571
1572 /* check for errors from OpenSSL */
1573 err = false;
1574 fflush(fp_smime_err);
1575 rewind(fp_smime_err);
1576 while (fgets(buf, sizeof(buf) - 1, fp_smime_err))
1577 {
1578 err = true;
1579 fputs(buf, stdout);
1580 }
1581 mutt_file_fclose(&fp_smime_err);
1582
1583 fflush(fp_smime_out);
1584 rewind(fp_smime_out);
1585 empty = (fgetc(fp_smime_out) == EOF);
1586 mutt_file_fclose(&fp_smime_out);
1587
1588 mutt_file_unlink(buf_string(filetosign));
1589
1590 if (err)
1592
1593 if (empty)
1594 {
1595 mutt_any_key_to_continue(_("No output from OpenSSL..."));
1596 mutt_file_unlink(buf_string(signedfile));
1597 goto cleanup; /* fatal error while signing */
1598 }
1599
1600 b_sign = mutt_body_new();
1601 b_sign->type = TYPE_MULTIPART;
1602 b_sign->subtype = mutt_str_dup("signed");
1603 b_sign->encoding = ENC_7BIT;
1604 b_sign->use_disp = false;
1605 b_sign->disposition = DISP_INLINE;
1606
1608
1609 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1610 char *micalg = openssl_md_to_smime_micalg(c_smime_sign_digest_alg);
1611 mutt_param_set(&b_sign->parameter, "micalg", micalg);
1612 FREE(&micalg);
1613
1614 mutt_param_set(&b_sign->parameter, "protocol", "application/pkcs7-signature");
1615
1616 b_sign->parts = b;
1617 rc = b_sign;
1618
1619 b_sign->parts->next = mutt_body_new();
1620 b_sign = b_sign->parts->next;
1621 b_sign->type = TYPE_APPLICATION;
1622 b_sign->subtype = mutt_str_dup("pkcs7-signature");
1623 b_sign->filename = buf_strdup(signedfile);
1624 b_sign->d_filename = mutt_str_dup("smime.p7s");
1625 b_sign->use_disp = true;
1626 b_sign->disposition = DISP_ATTACH;
1627 b_sign->encoding = ENC_BASE64;
1628 b_sign->unlink = true; /* ok to remove this file after sending. */
1629
1630cleanup:
1631 if (fp_sign)
1632 {
1633 mutt_file_fclose(&fp_sign);
1634 mutt_file_unlink(buf_string(filetosign));
1635 }
1636 if (fp_smime_out)
1637 {
1638 mutt_file_fclose(&fp_smime_out);
1639 mutt_file_unlink(buf_string(signedfile));
1640 }
1641 buf_pool_release(&filetosign);
1642 buf_pool_release(&signedfile);
1643 return rc;
1644}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:220
#define mutt_error(...)
Definition: logging2.h:92
#define FREE(x)
Definition: memory.h:45
@ ENC_BASE64
Base-64 encoded text.
Definition: mime.h:52
@ DISP_ATTACH
Content is attached.
Definition: mime.h:63
static struct Buffer SmimeIntermediateToUse
Smime intermediate certificate to use.
Definition: smime.c:79
static struct SmimeKey * smime_get_key_by_hash(const char *hash, bool only_public_key)
Find a key by its hash.
Definition: smime.c:532
static pid_t smime_invoke_sign(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)
Use SMIME to sign a file.
Definition: smime.c:1316
static char SmimePass[256]
Cached Smime Passphrase.
Definition: smime.c:70
static struct Buffer SmimeKeyToUse
Smime key to use.
Definition: smime.c:75
static struct Buffer SmimeCertToUse
Smime certificate to use.
Definition: smime.c:77
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition: smime.c:105
static char * openssl_md_to_smime_micalg(const char *md)
Change the algorithm names.
Definition: smime.c:1475
#define NONULL(x)
Definition: string2.h:37
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
An SIME key.
Definition: smime.h:43
char * issuer
Definition: smime.h:47
+ Here is the call graph for this function: