NeoMutt  2025-12-11-1040-g5187ba
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 1038 of file crypt_gpgme.c.

1039{
1040 return sign_message(b, from, false);
1041}
static struct Body * sign_message(struct Body *b, const struct AddressList *from, bool use_smime)
Sign a message.
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 1046 of file crypt_gpgme.c.

1047{
1048 return sign_message(b, from, true);
1049}
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 1349 of file pgp.c.

1350{
1352 struct Body *b_enc = NULL;
1353 struct Body *rv = NULL;
1354 char buf[1024] = { 0 };
1355 FILE *fp_pgp_in = NULL;
1356 FILE *fp_pgp_out = NULL;
1357 FILE *fp_pgp_err = NULL;
1358 FILE *fp_signed = NULL;
1359 bool err = false;
1360 bool empty = true;
1361 pid_t pid;
1362 struct Buffer *sigfile = buf_pool_get();
1363 struct Buffer *signedfile = buf_pool_get();
1364
1365 crypt_convert_to_7bit(b); /* Signed data _must_ be in 7-bit format. */
1366
1367 buf_mktemp(sigfile);
1368 FILE *fp_sig = mutt_file_fopen(buf_string(sigfile), "w");
1369 if (!fp_sig)
1370 {
1371 goto cleanup;
1372 }
1373
1374 buf_mktemp(signedfile);
1375 fp_signed = mutt_file_fopen(buf_string(signedfile), "w");
1376 if (!fp_signed)
1377 {
1378 mutt_perror("%s", buf_string(signedfile));
1379 mutt_file_fclose(&fp_sig);
1380 unlink(buf_string(sigfile));
1381 goto cleanup;
1382 }
1383
1384 mutt_write_mime_header(b, fp_signed, NeoMutt->sub);
1385 fputc('\n', fp_signed);
1386 mutt_write_mime_body(b, fp_signed, NeoMutt->sub);
1387 mutt_file_fclose(&fp_signed);
1388
1389 pid = pgp_invoke_sign(&fp_pgp_in, &fp_pgp_out, &fp_pgp_err, -1, -1, -1,
1390 buf_string(signedfile));
1391 if (pid == -1)
1392 {
1393 mutt_perror(_("Can't open PGP subprocess"));
1394 mutt_file_fclose(&fp_sig);
1395 unlink(buf_string(sigfile));
1396 unlink(buf_string(signedfile));
1397 goto cleanup;
1398 }
1399
1400 if (!pgp_use_gpg_agent())
1401 fputs(mod_data->pgp_pass, fp_pgp_in);
1402 fputc('\n', fp_pgp_in);
1403 mutt_file_fclose(&fp_pgp_in);
1404
1405 /* Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as
1406 * recommended for future releases of PGP. */
1407 while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1408 {
1409 if (mutt_str_equal("-----BEGIN PGP MESSAGE-----\n", buf))
1410 fputs("-----BEGIN PGP SIGNATURE-----\n", fp_sig);
1411 else if (mutt_str_equal("-----END PGP MESSAGE-----\n", buf))
1412 fputs("-----END PGP SIGNATURE-----\n", fp_sig);
1413 else
1414 fputs(buf, fp_sig);
1415 empty = false; /* got some output, so we're ok */
1416 }
1417
1418 /* check for errors from PGP */
1419 err = false;
1420 while (fgets(buf, sizeof(buf) - 1, fp_pgp_err))
1421 {
1422 err = true;
1423 fputs(buf, stdout);
1424 }
1425
1426 const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1427 if (filter_wait(pid) && c_pgp_check_exit)
1428 empty = true;
1429
1430 mutt_file_fclose(&fp_pgp_err);
1431 mutt_file_fclose(&fp_pgp_out);
1432 unlink(buf_string(signedfile));
1433
1434 if (mutt_file_fclose(&fp_sig) != 0)
1435 {
1436 mutt_perror("fclose");
1437 unlink(buf_string(sigfile));
1438 goto cleanup;
1439 }
1440
1441 if (err)
1443 if (empty)
1444 {
1445 unlink(buf_string(sigfile));
1446 /* most likely error is a bad passphrase, so automatically forget it */
1448 goto cleanup; /* fatal error while signing */
1449 }
1450
1451 b_enc = mutt_body_new();
1452 b_enc->type = TYPE_MULTIPART;
1453 b_enc->subtype = mutt_str_dup("signed");
1454 b_enc->encoding = ENC_7BIT;
1455 b_enc->use_disp = false;
1456 b_enc->disposition = DISP_INLINE;
1457 rv = b_enc;
1458
1460 mutt_param_set(&b_enc->parameter, "protocol", "application/pgp-signature");
1461 mutt_param_set(&b_enc->parameter, "micalg", pgp_micalg(buf_string(sigfile)));
1462
1463 b_enc->parts = b;
1464
1465 b_enc->parts->next = mutt_body_new();
1466 b_enc = b_enc->parts->next;
1467 b_enc->type = TYPE_APPLICATION;
1468 b_enc->subtype = mutt_str_dup("pgp-signature");
1469 b_enc->filename = buf_strdup(sigfile);
1470 b_enc->use_disp = false;
1471 b_enc->disposition = DISP_NONE;
1472 b_enc->encoding = ENC_7BIT;
1473 b_enc->unlink = true; /* ok to remove this file after sending. */
1474 mutt_param_set(&b_enc->parameter, "name", "signature.asc");
1475
1476cleanup:
1477 buf_pool_release(&sigfile);
1478 buf_pool_release(&signedfile);
1479 return rv;
1480}
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:96
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
void crypt_convert_to_7bit(struct Body *b)
Convert an email to 7bit encoding.
Definition crypt.c:815
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
#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_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
@ MODULE_ID_NCRYPT
ModuleNcrypt, Ncrypt
Definition module_api.h:82
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition multipart.c:93
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
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:666
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_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:204
const char * pgp_micalg(const char *fname)
Find the hash algorithm of a file.
Definition pgpmicalg.c:229
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
int mutt_write_mime_body(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition body.c:304
int mutt_write_mime_header(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition header.c:763
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
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
struct Body * next
next attachment in the list
Definition body.h:72
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:36
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
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 1384 of file smime.c.

1385{
1387 struct Body *b_sign = NULL;
1388 struct Body *rc = NULL;
1389 char buf[1024] = { 0 };
1390 struct Buffer *filetosign = NULL;
1391 struct Buffer *signedfile = NULL;
1392 FILE *fp_smime_in = NULL;
1393 FILE *fp_smime_out = NULL;
1394 FILE *fp_smime_err = NULL;
1395 FILE *fp_sign = NULL;
1396 bool err = false;
1397 int empty = 0;
1398 pid_t pid;
1399 const char *intermediates = NULL;
1400
1401 const char *const c_smime_sign_as = cs_subset_string(NeoMutt->sub, "smime_sign_as");
1402 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
1403 const char *signas = c_smime_sign_as ? c_smime_sign_as : c_smime_default_key;
1404 if (!signas || (*signas == '\0'))
1405 {
1406 mutt_error(_("Can't sign: No key specified. Use Sign As."));
1407 return NULL;
1408 }
1409
1410 crypt_convert_to_7bit(b); /* Signed data _must_ be in 7-bit format. */
1411
1412 filetosign = buf_pool_get();
1413 signedfile = buf_pool_get();
1414
1415 buf_mktemp(filetosign);
1416 fp_sign = mutt_file_fopen(buf_string(filetosign), "w+");
1417 if (!fp_sign)
1418 {
1419 mutt_perror("%s", buf_string(filetosign));
1420 goto cleanup;
1421 }
1422
1423 buf_mktemp(signedfile);
1424 fp_smime_out = mutt_file_fopen(buf_string(signedfile), "w+");
1425 if (!fp_smime_out)
1426 {
1427 mutt_perror("%s", buf_string(signedfile));
1428 goto cleanup;
1429 }
1430
1431 mutt_write_mime_header(b, fp_sign, NeoMutt->sub);
1432 fputc('\n', fp_sign);
1433 mutt_write_mime_body(b, fp_sign, NeoMutt->sub);
1434 mutt_file_fclose(&fp_sign);
1435
1436 const char *const c_smime_keys = cs_subset_path(NeoMutt->sub, "smime_keys");
1437 const char *const c_smime_certificates = cs_subset_path(NeoMutt->sub, "smime_certificates");
1438 buf_printf(&mod_data->smime_key_to_use, "%s/%s", NONULL(c_smime_keys), signas);
1439 buf_printf(&mod_data->smime_cert_to_use, "%s/%s", NONULL(c_smime_certificates), signas);
1440
1441 struct SmimeKey *signas_key = smime_get_key_by_hash(signas, 1);
1442 if (!signas_key || mutt_str_equal("?", signas_key->issuer))
1443 intermediates = signas; /* so openssl won't complain in any case */
1444 else
1445 intermediates = signas_key->issuer;
1446
1447 buf_printf(&mod_data->smime_intermediate_to_use, "%s/%s",
1448 NONULL(c_smime_certificates), intermediates);
1449
1450 smime_key_free(&signas_key);
1451
1452 pid = smime_invoke_sign(&fp_smime_in, NULL, &fp_smime_err, -1,
1453 fileno(fp_smime_out), -1, buf_string(filetosign));
1454 if (pid == -1)
1455 {
1456 mutt_perror(_("Can't open OpenSSL subprocess"));
1457 mutt_file_unlink(buf_string(filetosign));
1458 goto cleanup;
1459 }
1460 fputs(mod_data->smime_pass, fp_smime_in);
1461 fputc('\n', fp_smime_in);
1462 mutt_file_fclose(&fp_smime_in);
1463
1464 filter_wait(pid);
1465
1466 /* check for errors from OpenSSL */
1467 err = false;
1468 fflush(fp_smime_err);
1469 fseek(fp_smime_err, 0, SEEK_SET);
1470 clearerr(fp_smime_err);
1471 while (fgets(buf, sizeof(buf) - 1, fp_smime_err))
1472 {
1473 err = true;
1474 fputs(buf, stdout);
1475 }
1476 mutt_file_fclose(&fp_smime_err);
1477
1478 fflush(fp_smime_out);
1479 fseek(fp_smime_out, 0, SEEK_SET);
1480 clearerr(fp_smime_out);
1481 empty = (fgetc(fp_smime_out) == EOF);
1482 mutt_file_fclose(&fp_smime_out);
1483
1484 mutt_file_unlink(buf_string(filetosign));
1485
1486 if (err)
1487 {
1490 }
1491
1492 if (empty)
1493 {
1494 mutt_any_key_to_continue(_("No output from OpenSSL..."));
1495 mutt_file_unlink(buf_string(signedfile));
1496 goto cleanup; /* fatal error while signing */
1497 }
1498
1499 b_sign = mutt_body_new();
1500 b_sign->type = TYPE_MULTIPART;
1501 b_sign->subtype = mutt_str_dup("signed");
1502 b_sign->encoding = ENC_7BIT;
1503 b_sign->use_disp = false;
1504 b_sign->disposition = DISP_INLINE;
1505
1507
1508 const char *const c_smime_sign_digest_alg = cs_subset_string(NeoMutt->sub, "smime_sign_digest_alg");
1509 char *micalg = openssl_md_to_smime_micalg(c_smime_sign_digest_alg);
1510 mutt_param_set(&b_sign->parameter, "micalg", micalg);
1511 FREE(&micalg);
1512
1513 mutt_param_set(&b_sign->parameter, "protocol", "application/pkcs7-signature");
1514
1515 b_sign->parts = b;
1516 rc = b_sign;
1517
1518 b_sign->parts->next = mutt_body_new();
1519 b_sign = b_sign->parts->next;
1520 b_sign->type = TYPE_APPLICATION;
1521 b_sign->subtype = mutt_str_dup("pkcs7-signature");
1522 b_sign->filename = buf_strdup(signedfile);
1523 b_sign->d_filename = mutt_str_dup("smime.p7s");
1524 b_sign->use_disp = true;
1525 b_sign->disposition = DISP_ATTACH;
1526 b_sign->encoding = ENC_BASE64;
1527 b_sign->unlink = true; /* ok to remove this file after sending. */
1528
1529cleanup:
1530 if (fp_sign)
1531 {
1532 mutt_file_fclose(&fp_sign);
1533 mutt_file_unlink(buf_string(filetosign));
1534 }
1535 if (fp_smime_out)
1536 {
1537 mutt_file_fclose(&fp_smime_out);
1538 mutt_file_unlink(buf_string(signedfile));
1539 }
1540 buf_pool_release(&filetosign);
1541 buf_pool_release(&signedfile);
1542 return rc;
1543}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
void smime_class_void_passphrase(void)
Forget the cached passphrase - Implements CryptModuleSpecs::void_passphrase() -.
Definition smime.c:137
#define mutt_error(...)
Definition logging2.h:94
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:92
@ ENC_BASE64
Base-64 encoded text.
Definition mime.h:52
@ DISP_ATTACH
Content is attached.
Definition mime.h:63
static struct SmimeKey * smime_get_key_by_hash(const char *hash, bool only_public_key)
Find a key by its hash.
Definition smime.c:388
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:1196
static void smime_key_free(struct SmimeKey **keylist)
Free a list of SMIME keys.
Definition smime.c:91
static char * openssl_md_to_smime_micalg(const char *md)
Change the algorithm names.
Definition smime.c:1363
#define NONULL(x)
Definition string2.h:44
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition body.h:56
struct Buffer smime_cert_to_use
S/MIME certificate to use.
Definition module_data.h:59
char smime_pass[256]
Cached S/MIME Passphrase.
Definition module_data.h:56
struct Buffer smime_intermediate_to_use
S/MIME intermediate certificate to use.
Definition module_data.h:60
struct Buffer smime_key_to_use
S/MIME key to use.
Definition module_data.h:58
An SIME key.
Definition smime.h:43
char * issuer
Key issuer.
Definition smime.h:47
Here is the call graph for this function: