NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
crypt.c File Reference

Signing/encryption multiplexor. More...

#include "config.h"
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "crypt.h"
#include "lib.h"
#include "attach/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "cryptglue.h"
#include "handler.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "autocrypt/lib.h"
+ Include dependency graph for crypt.c:

Go to the source code of this file.

Functions

void crypt_current_time (struct State *s, const char *app_name)
 Print the current time. More...
 
void crypt_forget_passphrase (void)
 Forget a passphrase and display a message. More...
 
bool crypt_valid_passphrase (SecurityFlags flags)
 Check that we have a usable passphrase, ask if not. More...
 
int mutt_protect (struct Email *e, char *keylist, bool postpone)
 Encrypt and/or sign a message. More...
 
SecurityFlags mutt_is_multipart_signed (struct Body *b)
 Is a message signed? More...
 
SecurityFlags mutt_is_multipart_encrypted (struct Body *b)
 Does the message have encrypted parts? More...
 
int mutt_is_valid_multipart_pgp_encrypted (struct Body *b)
 Is this a valid multi-part encrypted message? More...
 
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted (struct Body *b)
 Check for malformed layout. More...
 
SecurityFlags mutt_is_application_pgp (struct Body *b)
 Does the message use PGP? More...
 
SecurityFlags mutt_is_application_smime (struct Body *b)
 Does the message use S/MIME? More...
 
SecurityFlags crypt_query (struct Body *b)
 Check out the type of encryption used. More...
 
int crypt_write_signed (struct Body *a, struct State *s, const char *tempfile)
 Write the message body/part. More...
 
void crypt_convert_to_7bit (struct Body *a)
 Convert an email to 7bit encoding. More...
 
void crypt_extract_keys_from_messages (struct Mailbox *m, struct EmailList *el)
 Extract keys from a message. More...
 
int crypt_get_keys (struct Email *e, char **keylist, bool oppenc_mode)
 Check we have all the keys we need. More...
 
void crypt_opportunistic_encrypt (struct Email *e)
 Can all recipients be determined. More...
 
static void crypt_fetch_signatures (struct Body ***signatures, struct Body *a, int *n)
 Create an array of an emails parts. More...
 
bool mutt_should_hide_protected_subject (struct Email *e)
 Should NeoMutt hide the protected subject? More...
 
int mutt_protected_headers_handler (struct Body *b, struct State *s)
 Process a protected header - Implements handler_t -. More...
 
int mutt_signed_handler (struct Body *b, struct State *s)
 Verify a "multipart/signed" body - Implements handler_t -. More...
 
const char * crypt_get_fingerprint_or_id (const char *p, const char **pphint, const char **ppl, const char **pps)
 Get the fingerprint or long key ID. More...
 
bool crypt_is_numerical_keyid (const char *s)
 Is this a numerical keyid. More...
 

Detailed Description

Signing/encryption multiplexor.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • Thomas Roessler
  • Oliver Ehli
  • Werner Koch
  • g10code GmbH
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file crypt.c.

Function Documentation

◆ crypt_current_time()

void crypt_current_time ( struct State s,
const char *  app_name 
)

Print the current time.

Parameters
sState to use
app_nameApp name, e.g. "PGP"

print the current time to avoid spoofing of the signature output

Definition at line 70 of file crypt.c.

71 {
72  char p[256], tmp[256];
73 
74  if (!WithCrypto)
75  return;
76 
77  const bool c_crypt_timestamp = cs_subset_bool(NeoMutt->sub, "crypt_timestamp");
78  if (c_crypt_timestamp)
79  {
80  mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), MUTT_DATE_NOW);
81  }
82  else
83  *p = '\0';
84 
85  snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
86  state_attach_puts(s, tmp);
87 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
#define MUTT_DATE_NOW
Constant representing the 'current time', see: mutt_date_gmtime(), mutt_date_localtime()
Definition: date.h:39
#define _(a)
Definition: message.h:28
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:100
#define WithCrypto
Definition: lib.h:116
#define NONULL(x)
Definition: string2.h:37
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:
+ Here is the caller graph for this function:

◆ crypt_forget_passphrase()

void crypt_forget_passphrase ( void  )

Forget a passphrase and display a message.

Definition at line 92 of file crypt.c.

93 {
96 
99 
100  if (WithCrypto)
101  {
102  /* L10N: Due to the implementation details (e.g. some passwords are managed
103  by gpg-agent) we can't know whether we forgot zero, 1, 12, ...
104  passwords. So in English we use "Passphrases". Your language might
105  have other means to express this. */
106  mutt_message(_("Passphrases forgotten"));
107  }
108 }
void crypt_smime_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:413
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:191
#define mutt_message(...)
Definition: logging.h:86
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_valid_passphrase()

bool crypt_valid_passphrase ( SecurityFlags  flags)

Check that we have a usable passphrase, ask if not.

Parameters
flagsFlags, see SecurityFlags
Return values
trueSuccess
falseFailed

Definition at line 134 of file crypt.c.

135 {
136  bool rc = false;
137 
138 #ifndef DEBUG
139  disable_coredumps();
140 #endif
141 
142  if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & APPLICATION_PGP))
144 
145  if (((WithCrypto & APPLICATION_SMIME) != 0) && (flags & APPLICATION_SMIME))
147 
148  return rc;
149 }
bool crypt_smime_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:422
bool crypt_pgp_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:200
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_protect()

int mutt_protect ( struct Email e,
char *  keylist,
bool  postpone 
)

Encrypt and/or sign a message.

Parameters
eEmail
keylistList of keys to encrypt to (space-separated)
postponeWhen true, signing is automatically disabled
Return values
0Success
-1Error

Definition at line 159 of file crypt.c.

160 {
161  struct Body *pbody = NULL, *tmp_pbody = NULL;
162  struct Body *tmp_smime_pbody = NULL;
163  struct Body *tmp_pgp_pbody = NULL;
164  bool has_retainable_sig = false;
165 
166  if (!WithCrypto)
167  return -1;
168 
169  SecurityFlags security = e->security;
170  int sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
171  if (postpone)
172  {
173  sign = SEC_NO_FLAGS;
174  security &= ~SEC_SIGN;
175  }
176 
177  if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
178  return 0;
179 
180  if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
181  return -1;
182 
183  if (((WithCrypto & APPLICATION_PGP) != 0) && !(security & SEC_AUTOCRYPT) &&
184  ((security & PGP_INLINE) == PGP_INLINE))
185  {
186  const enum QuadOption c_pgp_mime_auto = cs_subset_quad(NeoMutt->sub, "pgp_mime_auto");
187  if ((e->body->type != TYPE_TEXT) || !mutt_istr_equal(e->body->subtype, "plain"))
188  {
189  if (query_quadoption(c_pgp_mime_auto, _("Inline PGP can't be used with attachments. Revert to PGP/MIME?")) !=
190  MUTT_YES)
191  {
192  mutt_error(_("Mail not sent: inline PGP can't be used with attachments"));
193  return -1;
194  }
195  }
196  else if (mutt_istr_equal("flowed", mutt_param_get(&e->body->parameter, "format")))
197  {
198  if ((query_quadoption(c_pgp_mime_auto, _("Inline PGP can't be used with format=flowed. Revert to PGP/MIME?"))) !=
199  MUTT_YES)
200  {
201  mutt_error(_("Mail not sent: inline PGP can't be used with format=flowed"));
202  return -1;
203  }
204  }
205  else
206  {
207  /* they really want to send it inline... go for it */
208  if (!isendwin())
209  {
210  mutt_endwin();
211  puts(_("Invoking PGP..."));
212  }
213  pbody = crypt_pgp_traditional_encryptsign(e->body, security, keylist);
214  if (pbody)
215  {
216  e->body = pbody;
217  return 0;
218  }
219 
220  /* otherwise inline won't work...ask for revert */
221  if (query_quadoption(c_pgp_mime_auto,
222  _("Message can't be sent inline. Revert to using PGP/MIME?")) != MUTT_YES)
223  {
224  mutt_error(_("Mail not sent"));
225  return -1;
226  }
227  }
228 
229  /* go ahead with PGP/MIME */
230  }
231 
232  if (!isendwin())
233  mutt_endwin();
234 
236  tmp_smime_pbody = e->body;
238  tmp_pgp_pbody = e->body;
239 
240 #ifdef CRYPT_BACKEND_GPGME
241  const bool c_crypt_use_pka = cs_subset_bool(NeoMutt->sub, "crypt_use_pka");
242  if (sign && c_crypt_use_pka)
243 #else
244  if (sign)
245 #endif
246  {
247  /* Set sender (necessary for e.g. PKA). */
248  const char *mailbox = NULL;
249  struct Address *from = TAILQ_FIRST(&e->env->from);
250  bool free_from = false;
251 
252  if (!from)
253  {
254  free_from = true;
255  from = mutt_default_from(NeoMutt->sub);
256  }
257 
258  mailbox = from->mailbox;
259  const struct Address *c_envelope_from_address = cs_subset_address(NeoMutt->sub, "envelope_from_address");
260  if (!mailbox && c_envelope_from_address)
261  mailbox = c_envelope_from_address->mailbox;
262 
263  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
265  else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
267 
268  if (free_from)
269  mutt_addr_free(&from);
270  }
271 
272  const bool c_crypt_protected_headers_write = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_write");
273  if (c_crypt_protected_headers_write)
274  {
275  struct Envelope *protected_headers = mutt_env_new();
276  mutt_str_replace(&protected_headers->subject, e->env->subject);
277  /* Note: if other headers get added, such as to, cc, then a call to
278  * mutt_env_to_intl() will need to be added here too. */
279  mutt_prepare_envelope(protected_headers, 0, NeoMutt->sub);
280 
282  e->body->mime_headers = protected_headers;
283  mutt_param_set(&e->body->parameter, "protected-headers", "v1");
284  }
285 
286 #ifdef USE_AUTOCRYPT
287  /* A note about e->body->mime_headers. If postpone or send
288  * fails, the mime_headers is cleared out before returning to the
289  * compose menu. So despite the "robustness" code above and in the
290  * gen_gossip_list function below, mime_headers will not be set when
291  * entering mutt_protect().
292  *
293  * This is important to note because the user could toggle
294  * $crypt_protected_headers_write or $autocrypt off back in the
295  * compose menu. We don't want mutt_write_rfc822_header() to write
296  * stale data from one option if the other is set.
297  */
298  const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
299  if (c_autocrypt && !postpone && (security & SEC_AUTOCRYPT))
300  {
302  }
303 #endif
304 
305  if (sign)
306  {
307  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
308  {
309  tmp_pbody = crypt_smime_sign_message(e->body, &e->env->from);
310  if (!tmp_pbody)
311  goto bail;
312  pbody = tmp_pbody;
313  tmp_smime_pbody = tmp_pbody;
314  }
315 
316  const bool c_pgp_retainable_sigs = cs_subset_bool(NeoMutt->sub, "pgp_retainable_sigs");
317  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
318  (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || c_pgp_retainable_sigs))
319  {
320  tmp_pbody = crypt_pgp_sign_message(e->body, &e->env->from);
321  if (!tmp_pbody)
322  goto bail;
323 
324  has_retainable_sig = true;
325  sign = SEC_NO_FLAGS;
326  pbody = tmp_pbody;
327  tmp_pgp_pbody = tmp_pbody;
328  }
329 
330  if ((WithCrypto != 0) && (security & APPLICATION_SMIME) && (security & APPLICATION_PGP))
331  {
332  /* here comes the draft ;-) */
333  }
334  }
335 
336  if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
337  {
338  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
339  {
340  tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
341  if (!tmp_pbody)
342  {
343  /* signed ? free it! */
344  goto bail;
345  }
346  /* free tmp_body if messages was signed AND encrypted ... */
347  if ((tmp_smime_pbody != e->body) && (tmp_smime_pbody != tmp_pbody))
348  {
349  /* detach and don't delete e->body,
350  * which tmp_smime_pbody->parts after signing. */
351  tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
352  e->body->next = NULL;
353  mutt_body_free(&tmp_smime_pbody);
354  }
355  pbody = tmp_pbody;
356  }
357 
358  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
359  {
360  pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
361  if (!pbody)
362  {
363  /* did we perform a retainable signature? */
364  if (has_retainable_sig)
365  {
366  /* remove the outer multipart layer */
367  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
368  /* get rid of the signature */
369  mutt_body_free(&tmp_pgp_pbody->next);
370  }
371 
372  goto bail;
373  }
374 
375  // destroy temporary signature envelope when doing retainable signatures.
376  if (has_retainable_sig)
377  {
378  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
379  mutt_body_free(&tmp_pgp_pbody->next);
380  }
381  }
382  }
383 
384  if (pbody)
385  {
386  e->body = pbody;
387  return 0;
388  }
389 
390 bail:
392  mutt_param_delete(&e->body->parameter, "protected-headers");
393  return -1;
394 }
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:828
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: helpers.c:49
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
struct Body * crypt_pgp_traditional_encryptsign(struct Body *a, SecurityFlags flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:294
struct Body * crypt_smime_build_smime_entity(struct Body *a, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:497
struct Body * crypt_pgp_encrypt_message(struct Email *e, struct Body *a, char *keylist, int sign, const struct AddressList *from)
Wrapper for CryptModuleSpecs::pgp_encrypt_message()
Definition: cryptglue.c:338
struct Body * crypt_smime_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:486
void crypt_pgp_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:404
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:539
struct Body * crypt_pgp_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:327
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:355
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
#define mutt_error(...)
Definition: logging.h:87
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:126
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:87
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:74
#define PGP_INLINE
Definition: lib.h:100
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:77
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:386
#define TAILQ_FIRST(head)
Definition: queue.h:723
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition: send.c:1459
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:754
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
struct Body * next
next attachment in the list
Definition: body.h:71
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
struct Envelope * env
Envelope information.
Definition: email.h:66
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct Body * body
List of MIME parts.
Definition: email.h:67
The header of an Email.
Definition: envelope.h:57
char * subject
Email's subject.
Definition: envelope.h:70
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_multipart_signed()

SecurityFlags mutt_is_multipart_signed ( struct Body b)

Is a message signed?

Parameters
bBody of email
Return values
numMessage is signed, see SecurityFlags
0Message is not signed (SEC_NO_FLAGS)

Definition at line 402 of file crypt.c.

403 {
404  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "signed"))
405  {
406  return SEC_NO_FLAGS;
407  }
408 
409  char *p = mutt_param_get(&b->parameter, "protocol");
410  if (!p)
411  return SEC_NO_FLAGS;
412 
413  if (mutt_istr_equal(p, "multipart/mixed"))
414  return SEC_SIGN;
415 
416  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_istr_equal(p, "application/pgp-signature"))
417  {
418  return PGP_SIGN;
419  }
420 
421  if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_istr_equal(p, "application/x-pkcs7-signature"))
422  {
423  return SMIME_SIGN;
424  }
425  if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_istr_equal(p, "application/pkcs7-signature"))
426  {
427  return SMIME_SIGN;
428  }
429 
430  return SEC_NO_FLAGS;
431 }
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
#define PGP_SIGN
Definition: lib.h:97
#define SMIME_SIGN
Definition: lib.h:103
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_multipart_encrypted()

SecurityFlags mutt_is_multipart_encrypted ( struct Body b)

Does the message have encrypted parts?

Parameters
bBody of email
Return values
numMessage has got encrypted parts, see SecurityFlags
0Message hasn't got encrypted parts (SEC_NO_FLAGS)

Definition at line 439 of file crypt.c.

440 {
441  if ((WithCrypto & APPLICATION_PGP) == 0)
442  return SEC_NO_FLAGS;
443 
444  char *p = NULL;
445 
446  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
447  !mutt_istr_equal(b->subtype, "encrypted") ||
448  !(p = mutt_param_get(&b->parameter, "protocol")) ||
449  !mutt_istr_equal(p, "application/pgp-encrypted"))
450  {
451  return SEC_NO_FLAGS;
452  }
453 
454  return PGP_ENCRYPT;
455 }
#define PGP_ENCRYPT
Definition: lib.h:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_valid_multipart_pgp_encrypted()

int mutt_is_valid_multipart_pgp_encrypted ( struct Body b)

Is this a valid multi-part encrypted message?

Parameters
bBody of email
Return values
>0Message is valid, with encrypted parts, e.g. PGP_ENCRYPT
0Message hasn't got encrypted parts

Definition at line 463 of file crypt.c.

464 {
466  return 0;
467 
468  b = b->parts;
469  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
470  !mutt_istr_equal(b->subtype, "pgp-encrypted"))
471  {
472  return 0;
473  }
474 
475  b = b->next;
476  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
477  !mutt_istr_equal(b->subtype, "octet-stream"))
478  {
479  return 0;
480  }
481 
482  return PGP_ENCRYPT;
483 }
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:439
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_malformed_multipart_pgp_encrypted()

SecurityFlags mutt_is_malformed_multipart_pgp_encrypted ( struct Body b)

Check for malformed layout.

Parameters
bBody of email
Return values
numSuccess, see SecurityFlags
0Error, (SEC_NO_FLAGS)

This checks for the malformed layout caused by MS Exchange in some cases:

<multipart/mixed>
<text/plain>
<application/pgp-encrypted> [BASE64-encoded]
<application/octet-stream> [BASE64-encoded]

Definition at line 500 of file crypt.c.

501 {
502  if (!(WithCrypto & APPLICATION_PGP))
503  return SEC_NO_FLAGS;
504 
505  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
506  {
507  return SEC_NO_FLAGS;
508  }
509 
510  b = b->parts;
511  if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
512  !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
513  {
514  return SEC_NO_FLAGS;
515  }
516 
517  b = b->next;
518  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
519  !mutt_istr_equal(b->subtype, "pgp-encrypted"))
520  {
521  return SEC_NO_FLAGS;
522  }
523 
524  b = b->next;
525  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
526  !mutt_istr_equal(b->subtype, "octet-stream"))
527  {
528  return SEC_NO_FLAGS;
529  }
530 
531  b = b->next;
532  if (b)
533  return SEC_NO_FLAGS;
534 
535  return PGP_ENCRYPT;
536 }
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_application_pgp()

SecurityFlags mutt_is_application_pgp ( struct Body b)

Does the message use PGP?

Parameters
bBody of email
Return values
>0Message uses PGP, e.g. PGP_ENCRYPT
0Message doesn't use PGP, (SEC_NO_FLAGS)

Definition at line 544 of file crypt.c.

545 {
547  char *p = NULL;
548 
549  if (b->type == TYPE_APPLICATION)
550  {
551  if (mutt_istr_equal(b->subtype, "pgp") || mutt_istr_equal(b->subtype, "x-pgp-message"))
552  {
553  p = mutt_param_get(&b->parameter, "x-action");
554  if (p && (mutt_istr_equal(p, "sign") || mutt_istr_equal(p, "signclear")))
555  {
556  t |= PGP_SIGN;
557  }
558 
559  p = mutt_param_get(&b->parameter, "format");
560  if (p && mutt_istr_equal(p, "keys-only"))
561  {
562  t |= PGP_KEY;
563  }
564 
565  if (t == SEC_NO_FLAGS)
566  t |= PGP_ENCRYPT; /* not necessarily correct, but... */
567  }
568 
569  if (mutt_istr_equal(b->subtype, "pgp-signed"))
570  t |= PGP_SIGN;
571 
572  if (mutt_istr_equal(b->subtype, "pgp-keys"))
573  t |= PGP_KEY;
574  }
575  else if ((b->type == TYPE_TEXT) && mutt_istr_equal("plain", b->subtype))
576  {
577  if (((p = mutt_param_get(&b->parameter, "x-mutt-action")) ||
578  (p = mutt_param_get(&b->parameter, "x-action")) ||
579  (p = mutt_param_get(&b->parameter, "action"))) &&
580  mutt_istr_startswith(p, "pgp-sign"))
581  {
582  t |= PGP_SIGN;
583  }
584  else if (p && mutt_istr_startswith(p, "pgp-encrypt"))
585  t |= PGP_ENCRYPT;
586  else if (p && mutt_istr_startswith(p, "pgp-keys"))
587  t |= PGP_KEY;
588  }
589  if (t)
590  t |= PGP_INLINE;
591 
592  return t;
593 }
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:239
#define PGP_KEY
Definition: lib.h:99
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_application_smime()

SecurityFlags mutt_is_application_smime ( struct Body b)

Does the message use S/MIME?

Parameters
bBody of email
Return values
>0Message uses S/MIME, e.g. SMIME_ENCRYPT
0Message doesn't use S/MIME, (SEC_NO_FLAGS)

Definition at line 601 of file crypt.c.

602 {
603  if (!b)
604  return SEC_NO_FLAGS;
605 
606  if (((b->type & TYPE_APPLICATION) == 0) || !b->subtype)
607  return SEC_NO_FLAGS;
608 
609  char *t = NULL;
610  bool complain = false;
611  /* S/MIME MIME types don't need x- anymore, see RFC2311 */
612  if (mutt_istr_equal(b->subtype, "x-pkcs7-mime") || mutt_istr_equal(b->subtype, "pkcs7-mime"))
613  {
614  t = mutt_param_get(&b->parameter, "smime-type");
615  if (t)
616  {
617  if (mutt_istr_equal(t, "enveloped-data"))
618  return SMIME_ENCRYPT;
619  if (mutt_istr_equal(t, "signed-data"))
620  return SMIME_SIGN | SMIME_OPAQUE;
621  return SEC_NO_FLAGS;
622  }
623  /* Netscape 4.7 uses
624  * Content-Description: S/MIME Encrypted Message
625  * instead of Content-Type parameter */
626  if (mutt_istr_equal(b->description, "S/MIME Encrypted Message"))
627  return SMIME_ENCRYPT;
628  complain = true;
629  }
630  else if (!mutt_istr_equal(b->subtype, "octet-stream"))
631  return SEC_NO_FLAGS;
632 
633  t = mutt_param_get(&b->parameter, "name");
634 
635  if (!t)
636  t = b->d_filename;
637  if (!t)
638  t = b->filename;
639  if (!t)
640  {
641  if (complain)
642  {
643  mutt_message(_("S/MIME messages with no hints on content are unsupported"));
644  }
645  return SEC_NO_FLAGS;
646  }
647 
648  /* no .p7c, .p10 support yet. */
649 
650  int len = mutt_str_len(t) - 4;
651  if ((len > 0) && (*(t + len) == '.'))
652  {
653  len++;
654  if (mutt_istr_equal((t + len), "p7m"))
655  {
656  /* Not sure if this is the correct thing to do, but
657  * it's required for compatibility with Outlook */
658  return SMIME_SIGN | SMIME_OPAQUE;
659  }
660  else if (mutt_istr_equal((t + len), "p7s"))
661  return SMIME_SIGN | SMIME_OPAQUE;
662  }
663 
664  return SEC_NO_FLAGS;
665 }
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
#define SMIME_OPAQUE
Definition: lib.h:106
#define SMIME_ENCRYPT
Definition: lib.h:102
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
char * description
content-description
Definition: body.h:55
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:
+ Here is the caller graph for this function:

◆ crypt_query()

SecurityFlags crypt_query ( struct Body b)

Check out the type of encryption used.

Parameters
bBody of email
Return values
numFlags, see SecurityFlags
0Error (SEC_NO_FLAGS)

Set the cached status values if there are any.

Definition at line 675 of file crypt.c.

676 {
677  if (!WithCrypto || !b)
678  return SEC_NO_FLAGS;
679 
681 
682  if (b->type == TYPE_APPLICATION)
683  {
685  rc |= mutt_is_application_pgp(b);
686 
688  {
689  rc |= mutt_is_application_smime(b);
690  if (rc && b->goodsig)
691  rc |= SEC_GOODSIGN;
692  if (rc && b->badsig)
693  rc |= SEC_BADSIGN;
694  }
695  }
696  else if (((WithCrypto & APPLICATION_PGP) != 0) && (b->type == TYPE_TEXT))
697  {
698  rc |= mutt_is_application_pgp(b);
699  if (rc && b->goodsig)
700  rc |= SEC_GOODSIGN;
701  }
702 
703  if (b->type == TYPE_MULTIPART)
704  {
706  rc |= mutt_is_multipart_signed(b);
708 
709  if (rc && b->goodsig)
710  rc |= SEC_GOODSIGN;
711 #ifdef USE_AUTOCRYPT
712  if (rc && b->is_autocrypt)
713  rc |= SEC_AUTOCRYPT;
714 #endif
715  }
716 
717  if ((b->type == TYPE_MULTIPART) || (b->type == TYPE_MESSAGE))
718  {
719  SecurityFlags u = b->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
720  SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
721 
722  for (b = b->parts; b; b = b->next)
723  {
724  const SecurityFlags v = crypt_query(b);
725  u &= v;
726  w |= v;
727  }
728  rc |= u | (w & ~SEC_GOODSIGN);
729 
730  if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
731  rc |= SEC_PARTSIGN;
732  }
733 
734  return rc;
735 }
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:544
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:402
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:500
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:675
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
#define SEC_ALL_FLAGS
Definition: lib.h:94
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:80
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:81
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:82
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:43
bool is_autocrypt
Flag autocrypt-decrypted messages for replying.
Definition: body.h:50
bool goodsig
Good cryptographic signature.
Definition: body.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_write_signed()

int crypt_write_signed ( struct Body a,
struct State s,
const char *  tempfile 
)

Write the message body/part.

Parameters
aBody to write
sState to use
tempfileFile to write to
Return values
0Success
-1Error

Body/part A described by state S to the given TEMPFILE.

Definition at line 747 of file crypt.c.

748 {
749  if (!WithCrypto)
750  return -1;
751 
752  FILE *fp = mutt_file_fopen(tempfile, "w");
753  if (!fp)
754  {
755  mutt_perror(tempfile);
756  return -1;
757  }
758 
759  if (!mutt_file_seek(s->fp_in, a->hdr_offset, SEEK_SET))
760  {
761  mutt_file_fclose(&fp);
762  return -1;
763  }
764  size_t bytes = a->length + a->offset - a->hdr_offset;
765  bool hadcr = false;
766  while (bytes > 0)
767  {
768  const int c = fgetc(s->fp_in);
769  if (c == EOF)
770  break;
771 
772  bytes--;
773 
774  if (c == '\r')
775  hadcr = true;
776  else
777  {
778  if ((c == '\n') && !hadcr)
779  fputc('\r', fp);
780 
781  hadcr = false;
782  }
783 
784  fputc(c, fp);
785  }
786  mutt_file_fclose(&fp);
787 
788  return 0;
789 }
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
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
#define mutt_perror(...)
Definition: logging.h:88
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:80
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:

◆ crypt_convert_to_7bit()

void crypt_convert_to_7bit ( struct Body a)

Convert an email to 7bit encoding.

Parameters
aBody of email to convert

Definition at line 795 of file crypt.c.

796 {
797  if (!WithCrypto)
798  return;
799 
800  const bool c_pgp_strict_enc = cs_subset_bool(NeoMutt->sub, "pgp_strict_enc");
801  while (a)
802  {
803  if (a->type == TYPE_MULTIPART)
804  {
805  if (a->encoding != ENC_7BIT)
806  {
807  a->encoding = ENC_7BIT;
809  }
810  else if (((WithCrypto & APPLICATION_PGP) != 0) && c_pgp_strict_enc)
812  }
813  else if ((a->type == TYPE_MESSAGE) && !mutt_istr_equal(a->subtype, "delivery-status"))
814  {
815  if (a->encoding != ENC_7BIT)
816  mutt_message_to_7bit(a, NULL, NeoMutt->sub);
817  }
818  else if (a->encoding == ENC_8BIT)
820  else if (a->encoding == ENC_BINARY)
821  a->encoding = ENC_BASE64;
822  else if (a->content && (a->encoding != ENC_BASE64) &&
823  (a->content->from || (a->content->space && c_pgp_strict_enc)))
824  {
826  }
827  a = a->next;
828  }
829 }
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:795
@ ENC_7BIT
7-bit text
Definition: mime.h:49
@ ENC_BINARY
Binary.
Definition: mime.h:53
@ ENC_BASE64
Base-64 encoded text.
Definition: mime.h:52
@ ENC_8BIT
8-bit text
Definition: mime.h:50
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
Definition: mime.h:51
void mutt_message_to_7bit(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Convert an email's MIME parts to 7-bit.
Definition: sendlib.c:254
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:69
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
bool space
Whitespace at the end of lines?
Definition: content.h:42
bool from
Has a line beginning with "From "?
Definition: content.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_extract_keys_from_messages()

void crypt_extract_keys_from_messages ( struct Mailbox m,
struct EmailList *  el 
)

Extract keys from a message.

Parameters
mMailbox
elList of Emails to process

The extracted keys will be added to the user's keyring.

Definition at line 838 of file crypt.c.

839 {
840  if (!WithCrypto)
841  return;
842 
843  struct Buffer *tempfname = mutt_buffer_pool_get();
844  mutt_buffer_mktemp(tempfname);
845  FILE *fp_out = mutt_file_fopen(mutt_buffer_string(tempfname), "w");
846  if (!fp_out)
847  {
848  mutt_perror(mutt_buffer_string(tempfname));
849  goto cleanup;
850  }
851 
853  OptDontHandlePgpKeys = true;
854 
855  struct EmailNode *en = NULL;
856  STAILQ_FOREACH(en, el, entries)
857  {
858  struct Email *e = en->email;
859  struct Message *msg = mx_msg_open(m, e->msgno);
860  if (!msg)
861  {
862  continue;
863  }
864  mutt_parse_mime_message(e, msg->fp);
866  {
867  mx_msg_close(m, &msg);
868  mutt_file_fclose(&fp_out);
869  break;
870  }
871 
872  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
873  {
875  fflush(fp_out);
876 
877  mutt_endwin();
878  puts(_("Trying to extract PGP keys...\n"));
880  }
881 
882  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
883  {
884  const bool encrypt = e->security & SEC_ENCRYPT;
885  mutt_copy_message(fp_out, e, msg,
888  CH_NO_FLAGS, 0);
889  fflush(fp_out);
890 
891  char *mbox = NULL;
892  if (!TAILQ_EMPTY(&e->env->from))
893  {
895  mbox = TAILQ_FIRST(&e->env->from)->mailbox;
896  }
897  else if (!TAILQ_EMPTY(&e->env->sender))
898  {
900  mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
901  }
902  if (mbox)
903  {
904  mutt_endwin();
905  puts(_("Trying to extract S/MIME certificates..."));
907  }
908  }
909  mx_msg_close(m, &msg);
910 
911  rewind(fp_out);
912  }
913 
914  mutt_file_fclose(&fp_out);
915  if (isendwin())
917 
919 
921  OptDontHandlePgpKeys = false;
922 
923 cleanup:
924  mutt_buffer_pool_release(&tempfname);
925 }
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:298
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:592
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_copy_message(FILE *fp_out, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:864
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:38
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:42
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:46
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
#define MUTT_CM_DECODE_CRYPT
Definition: copy.h:48
#define MUTT_CM_NOHEADER
Don't copy the message header.
Definition: copy.h:36
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:51
void crypt_pgp_invoke_import(const char *fname)
Wrapper for CryptModuleSpecs::pgp_invoke_import()
Definition: cryptglue.c:364
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import()
Definition: cryptglue.c:508
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1193
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1147
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:41
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
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define TAILQ_EMPTY(head)
Definition: queue.h:721
String manipulation buffer.
Definition: buffer.h:34
List of Emails.
Definition: email.h:131
struct Email * email
Email in the list.
Definition: email.h:132
The envelope/body of an email.
Definition: email.h:37
int msgno
Number displayed to the user.
Definition: email.h:111
struct AddressList sender
Email's sender.
Definition: envelope.h:63
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_get_keys()

int crypt_get_keys ( struct Email e,
char **  keylist,
bool  oppenc_mode 
)

Check we have all the keys we need.

Parameters
[in]eEmail with addresses to match
[out]keylistKeys needed
[in]oppenc_modeIf true, use opportunistic encryption
Return values
0Success
-1Error

Do a quick check to make sure that we can find all of the encryption keys if the user has requested this service. Return the list of keys in KEYLIST. If oppenc_mode is true, only keys that can be determined without prompting will be used.

Definition at line 941 of file crypt.c.

942 {
943  if (!WithCrypto)
944  return 0;
945 
946  struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
947  const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
948  const char *self_encrypt = NULL;
949 
950  /* Do a quick check to make sure that we can find all of the encryption
951  * keys if the user has requested this service. */
952 
953  *keylist = NULL;
954 
955 #ifdef USE_AUTOCRYPT
956  if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
957  {
959  return -1;
960  return 0;
961  }
962 #endif
963 
965  OptPgpCheckTrust = true;
966 
967  mutt_addrlist_copy(&addrlist, &e->env->to, false);
968  mutt_addrlist_copy(&addrlist, &e->env->cc, false);
969  mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
970  mutt_addrlist_qualify(&addrlist, fqdn);
971  mutt_addrlist_dedupe(&addrlist);
972 
973  if (oppenc_mode || (e->security & SEC_ENCRYPT))
974  {
975  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
976  {
977  *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
978  if (!*keylist)
979  {
980  mutt_addrlist_clear(&addrlist);
981  return -1;
982  }
983  OptPgpCheckTrust = false;
984  const bool c_pgp_self_encrypt = cs_subset_bool(NeoMutt->sub, "pgp_self_encrypt");
985  const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
986  const enum QuadOption c_pgp_encrypt_self = cs_subset_quad(NeoMutt->sub, "pgp_encrypt_self");
987  if (c_pgp_self_encrypt || (c_pgp_encrypt_self == MUTT_YES))
988  self_encrypt = c_pgp_default_key;
989  }
990  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
991  {
992  *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
993  if (!*keylist)
994  {
995  mutt_addrlist_clear(&addrlist);
996  return -1;
997  }
998  const bool c_smime_self_encrypt = cs_subset_bool(NeoMutt->sub, "smime_self_encrypt");
999  const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
1000  const enum QuadOption c_smime_encrypt_self = cs_subset_quad(NeoMutt->sub, "smime_encrypt_self");
1001  if (c_smime_self_encrypt || (c_smime_encrypt_self == MUTT_YES))
1002  self_encrypt = c_smime_default_key;
1003  }
1004  }
1005 
1006  if (!oppenc_mode && self_encrypt)
1007  {
1008  const size_t keylist_size = mutt_str_len(*keylist);
1009  mutt_mem_realloc(keylist, keylist_size + mutt_str_len(self_encrypt) + 2);
1010  sprintf(*keylist + keylist_size, " %s", self_encrypt);
1011  }
1012 
1013  mutt_addrlist_clear(&addrlist);
1014 
1015  return 0;
1016 }
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1407
@ AUTOCRYPT_REC_NO
Do no use Autocrypt.
Definition: lib.h:159
enum AutocryptRec mutt_autocrypt_ui_recommendation(const struct Email *e, char **keylist)
Get the recommended action for an Email.
Definition: autocrypt.c:567
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * crypt_smime_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:475
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:316
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:54
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:698
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_opportunistic_encrypt()

void crypt_opportunistic_encrypt ( struct Email e)

Can all recipients be determined.

Parameters
eEmail

Check if all recipients keys can be automatically determined. Enable encryption if they can, otherwise disable encryption.

Definition at line 1025 of file crypt.c.

1026 {
1027  if (!WithCrypto)
1028  return;
1029 
1030  const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
1031  if (!(c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT)))
1032  return;
1033 
1034  char *pgpkeylist = NULL;
1035 
1036  crypt_get_keys(e, &pgpkeylist, 1);
1037  if (pgpkeylist)
1038  {
1039  e->security |= SEC_ENCRYPT;
1040  FREE(&pgpkeylist);
1041  }
1042  else
1043  {
1044  e->security &= ~SEC_ENCRYPT;
1045  }
1046 }
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:941
#define FREE(x)
Definition: memory.h:43
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_fetch_signatures()

static void crypt_fetch_signatures ( struct Body ***  signatures,
struct Body a,
int *  n 
)
static

Create an array of an emails parts.

Parameters
[out]signaturesArray of Body parts
[in]aBody part to examine
[out]nCumulative count of parts

Definition at line 1054 of file crypt.c.

1055 {
1056  if (!WithCrypto)
1057  return;
1058 
1059  for (; a; a = a->next)
1060  {
1061  if (a->type == TYPE_MULTIPART)
1062  crypt_fetch_signatures(signatures, a->parts, n);
1063  else
1064  {
1065  if ((*n % 5) == 0)
1066  mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1067 
1068  (*signatures)[(*n)++] = a;
1069  }
1070  }
1071 }
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1054
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_should_hide_protected_subject()

bool mutt_should_hide_protected_subject ( struct Email e)

Should NeoMutt hide the protected subject?

Parameters
eEmail to test
Return values
trueThe subject should be protected

Definition at line 1078 of file crypt.c.

1079 {
1080  const bool c_crypt_protected_headers_write = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_write");
1081  const char *const c_crypt_protected_headers_subject =
1082  cs_subset_string(NeoMutt->sub, "crypt_protected_headers_subject");
1083  if (c_crypt_protected_headers_write && (e->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) &&
1084  !(e->security & SEC_INLINE) && c_crypt_protected_headers_subject)
1085  {
1086  return true;
1087  }
1088 
1089  return false;
1090 }
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:85
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_get_fingerprint_or_id()

const char* crypt_get_fingerprint_or_id ( const char *  p,
const char **  pphint,
const char **  ppl,
const char **  pps 
)

Get the fingerprint or long key ID.

Parameters
[in]pString to examine
[out]pphintStart of string to be passed to pgp_add_string_to_hints() or crypt_add_string_to_hints()
[out]pplStart of long key ID if detected, else NULL
[out]ppsStart of short key ID if detected, else NULL
Return values
ptrCopy of fingerprint, if any, stripped of all spaces. Must be FREE'd by caller
NULLOtherwise

Obtain pointers to fingerprint or short or long key ID, if any.

Upon return, at most one of return, *ppl and *pps pointers is non-NULL, indicating the longest fingerprint or ID found, if any.

Definition at line 1263 of file crypt.c.

1265 {
1266  const char *ps = NULL, *pl = NULL, *phint = NULL;
1267  char *pfcopy = NULL, *s1 = NULL, *s2 = NULL;
1268  char c;
1269  int isid;
1270  size_t hexdigits;
1271 
1272  /* User input may be partial name, fingerprint or short or long key ID,
1273  * independent of `$pgp_long_ids`.
1274  * Fingerprint without spaces is 40 hex digits (SHA-1) or 32 hex digits (MD5).
1275  * Strip leading "0x" for key ID detection and prepare pl and ps to indicate
1276  * if an ID was found and to simplify logic in the key loop's inner
1277  * condition of the caller. */
1278 
1279  char *pf = mutt_str_skip_whitespace(p);
1280  if (mutt_istr_startswith(pf, "0x"))
1281  pf += 2;
1282 
1283  /* Check if a fingerprint is given, must be hex digits only, blanks
1284  * separating groups of 4 hex digits are allowed. Also pre-check for ID. */
1285  isid = 2; /* unknown */
1286  hexdigits = 0;
1287  s1 = pf;
1288  do
1289  {
1290  c = *(s1++);
1291  if ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) ||
1292  (('a' <= c) && (c <= 'f')))
1293  {
1294  hexdigits++;
1295  if (isid == 2)
1296  isid = 1; /* it is an ID so far */
1297  }
1298  else if (c)
1299  {
1300  isid = 0; /* not an ID */
1301  if ((c == ' ') && ((hexdigits % 4) == 0))
1302  ; /* skip blank before or after 4 hex digits */
1303  else
1304  break; /* any other character or position */
1305  }
1306  } while (c);
1307 
1308  /* If at end of input, check for correct fingerprint length and copy if. */
1309  pfcopy = (!c && ((hexdigits == 40) || (hexdigits == 32)) ? mutt_str_dup(pf) : NULL);
1310 
1311  if (pfcopy)
1312  {
1313  /* Use pfcopy to strip all spaces from fingerprint and as hint. */
1314  s1 = pfcopy;
1315  s2 = pfcopy;
1316  do
1317  {
1318  *(s1++) = *(s2 = mutt_str_skip_whitespace(s2));
1319  } while (*(s2++));
1320 
1321  phint = pfcopy;
1322  ps = NULL;
1323  pl = NULL;
1324  }
1325  else
1326  {
1327  phint = p;
1328  ps = NULL;
1329  pl = NULL;
1330  if (isid == 1)
1331  {
1332  if (mutt_str_len(pf) == 16)
1333  pl = pf; /* long key ID */
1334  else if (mutt_str_len(pf) == 8)
1335  ps = pf; /* short key ID */
1336  }
1337  }
1338 
1339  *pphint = phint;
1340  *ppl = pl;
1341  *pps = ps;
1342  return pfcopy;
1343 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:599
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_is_numerical_keyid()

bool crypt_is_numerical_keyid ( const char *  s)

Is this a numerical keyid.

Parameters
sKey to test
Return values
trueKeyid is numeric

Check if a crypt-hook value is a key id.

Definition at line 1352 of file crypt.c.

1353 {
1354  /* or should we require the "0x"? */
1355  if (mutt_strn_equal(s, "0x", 2))
1356  s += 2;
1357  if (strlen(s) % 8)
1358  return false;
1359  while (*s)
1360  if (!strchr("0123456789ABCDEFabcdef", *s++))
1361  return false;
1362 
1363  return true;
1364 }
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:473
+ Here is the call graph for this function:
+ Here is the caller graph for this function: