NeoMutt  2020-06-26-89-g172cd3
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 "private.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 "copy.h"
#include "cryptglue.h"
#include "handler.h"
#include "mutt_globals.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "options.h"
#include "state.h"
#include "ncrypt/lib.h"
#include "send/lib.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 *m)
 Does the message use PGP? More...
 
SecurityFlags mutt_is_application_smime (struct Body *m)
 Does the message use S/MIME? More...
 
SecurityFlags crypt_query (struct Body *m)
 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 *a, struct State *s)
 Process a protected header - Implements handler_t. More...
 
int mutt_signed_handler (struct Body *a, 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 71 of file crypt.c.

72 {
73  char p[256], tmp[256];
74 
75  if (!WithCrypto)
76  return;
77 
78  if (C_CryptTimestamp)
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 }
#define NONULL(x)
Definition: string2.h:37
#define WithCrypto
Definition: lib.h:118
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:678
#define _(a)
Definition: message.h:28
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:37
bool C_CryptTimestamp
Config: Add a timestamp to PGP or SMIME output to prevent spoofing.
Definition: config.c:59
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
+ 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 }
#define WithCrypto
Definition: lib.h:118
#define mutt_message(...)
Definition: logging.h:83
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:187
#define _(a)
Definition: message.h:28
void crypt_smime_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:411
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
+ 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 }
#define WithCrypto
Definition: lib.h:118
bool crypt_smime_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:420
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
bool crypt_pgp_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:196
+ 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  int 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  if ((e->content->type != TYPE_TEXT) || !mutt_istr_equal(e->content->subtype, "plain"))
187  {
189  _("Inline PGP can't be used with attachments. "
190  "Revert to PGP/MIME?")) != MUTT_YES)
191  {
192  mutt_error(
193  _("Mail not sent: inline PGP can't be used with attachments"));
194  return -1;
195  }
196  }
197  else if (mutt_istr_equal("flowed", mutt_param_get(&e->content->parameter, "format")))
198  {
200  _("Inline PGP can't be used with format=flowed. "
201  "Revert to PGP/MIME?"))) != MUTT_YES)
202  {
203  mutt_error(
204  _("Mail not sent: inline PGP can't be used with format=flowed"));
205  return -1;
206  }
207  }
208  else
209  {
210  /* they really want to send it inline... go for it */
211  if (!isendwin())
212  {
213  mutt_endwin();
214  puts(_("Invoking PGP..."));
215  }
216  pbody = crypt_pgp_traditional_encryptsign(e->content, security, keylist);
217  if (pbody)
218  {
219  e->content = pbody;
220  return 0;
221  }
222 
223  /* otherwise inline won't work...ask for revert */
224  if (query_quadoption(
226  _("Message can't be sent inline. Revert to using PGP/MIME?")) != MUTT_YES)
227  {
228  mutt_error(_("Mail not sent"));
229  return -1;
230  }
231  }
232 
233  /* go ahead with PGP/MIME */
234  }
235 
236  if (!isendwin())
237  mutt_endwin();
238 
240  tmp_smime_pbody = e->content;
241  if (WithCrypto & APPLICATION_PGP)
242  tmp_pgp_pbody = e->content;
243 
244 #ifdef CRYPT_BACKEND_GPGME
245  if (sign && C_CryptUsePka)
246 #else
247  if (sign)
248 #endif
249  {
250  /* Set sender (necessary for e.g. PKA). */
251  const char *mailbox = NULL;
252  struct Address *from = TAILQ_FIRST(&e->env->from);
253  bool free_from = false;
254 
255  if (!from)
256  {
257  free_from = true;
258  from = mutt_default_from(NeoMutt->sub);
259  }
260 
261  mailbox = from->mailbox;
262  if (!mailbox && C_EnvelopeFromAddress)
263  mailbox = C_EnvelopeFromAddress->mailbox;
264 
265  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
266  crypt_smime_set_sender(mailbox);
267  else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
268  crypt_pgp_set_sender(mailbox);
269 
270  if (free_from)
271  mutt_addr_free(&from);
272  }
273 
275  {
276  struct Envelope *protected_headers = mutt_env_new();
277  mutt_str_replace(&protected_headers->subject, e->env->subject);
278  /* Note: if other headers get added, such as to, cc, then a call to
279  * mutt_env_to_intl() will need to be added here too. */
280  mutt_prepare_envelope(protected_headers, 0, NeoMutt->sub);
281 
283  e->content->mime_headers = protected_headers;
284  /* Optional part of the draft RFC, but required by Enigmail */
285  mutt_param_set(&e->content->parameter, "protected-headers", "v1");
286  }
287  else
288  {
289  mutt_param_delete(&e->content->parameter, "protected-headers");
290  }
291 
292 #ifdef USE_AUTOCRYPT
293  /* A note about e->content->mime_headers. If postpone or send
294  * fails, the mime_headers is cleared out before returning to the
295  * compose menu. So despite the "robustness" code above and in the
296  * gen_gossip_list function below, mime_headers will not be set when
297  * entering mutt_protect().
298  *
299  * This is important to note because the user could toggle
300  * $crypt_protected_headers_write or $autocrypt off back in the
301  * compose menu. We don't want mutt_write_rfc822_header() to write
302  * stale data from one option if the other is set.
303  */
304  if (C_Autocrypt && !postpone && (security & SEC_AUTOCRYPT))
305  {
307  }
308 #endif
309 
310  if (sign)
311  {
312  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
313  {
314  tmp_pbody = crypt_smime_sign_message(e->content, &e->env->from);
315  if (!tmp_pbody)
316  goto bail;
317  pbody = tmp_pbody;
318  tmp_smime_pbody = tmp_pbody;
319  }
320 
321  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
322  (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || C_PgpRetainableSigs))
323  {
324  tmp_pbody = crypt_pgp_sign_message(e->content, &e->env->from);
325  if (!tmp_pbody)
326  goto bail;
327 
328  has_retainable_sig = true;
329  sign = SEC_NO_FLAGS;
330  pbody = tmp_pbody;
331  tmp_pgp_pbody = tmp_pbody;
332  }
333 
334  if ((WithCrypto != 0) && (security & APPLICATION_SMIME) && (security & APPLICATION_PGP))
335  {
336  /* here comes the draft ;-) */
337  }
338  }
339 
340  if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
341  {
342  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
343  {
344  tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
345  if (!tmp_pbody)
346  {
347  /* signed ? free it! */
348  goto bail;
349  }
350  /* free tmp_body if messages was signed AND encrypted ... */
351  if ((tmp_smime_pbody != e->content) && (tmp_smime_pbody != tmp_pbody))
352  {
353  /* detach and don't delete e->content,
354  * which tmp_smime_pbody->parts after signing. */
355  tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
356  e->content->next = NULL;
357  mutt_body_free(&tmp_smime_pbody);
358  }
359  pbody = tmp_pbody;
360  }
361 
362  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
363  {
364  pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
365  if (!pbody)
366  {
367  /* did we perform a retainable signature? */
368  if (has_retainable_sig)
369  {
370  /* remove the outer multipart layer */
371  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
372  /* get rid of the signature */
373  mutt_body_free(&tmp_pgp_pbody->next);
374  }
375 
376  goto bail;
377  }
378 
379  // destroy temporary signature envelope when doing retainable signatures.
380  if (has_retainable_sig)
381  {
382  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
383  mutt_body_free(&tmp_pgp_pbody->next);
384  }
385  }
386  }
387 
388  if (pbody)
389  {
390  e->content = pbody;
391  return 0;
392  }
393 
394 bail:
396  return -1;
397 }
#define PGP_INLINE
Definition: lib.h:102
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define WithCrypto
Definition: lib.h:118
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: config.c:37
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:80
struct Body * content
List of MIME parts.
Definition: email.h:90
void crypt_pgp_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:402
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
unsigned char C_PgpMimeAuto
Config: Prompt the user to use MIME if inline PGP fails.
Definition: config.c:61
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:89
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:539
struct Body * crypt_smime_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:486
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:1235
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
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:336
bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: config.c:38
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:125
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:569
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default &#39;from&#39; Address.
Definition: send.c:1323
Type: &#39;text/*&#39;.
Definition: mime.h:38
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
struct Body * crypt_pgp_traditional_encryptsign(struct Body *a, int flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:292
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
bool C_PgpRetainableSigs
Config: Create nested multipart/signed or encrypted messages.
Definition: config.c:62
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define SEC_SIGN
Email is signed.
Definition: lib.h:81
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:515
struct Body * crypt_smime_build_smime_entity(struct Body *a, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:497
char * subject
Email&#39;s subject.
Definition: envelope.h:66
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:784
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
#define mutt_error(...)
Definition: logging.h:84
struct Body * crypt_pgp_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:325
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: config.c:58
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
The header of an Email.
Definition: envelope.h:54
bool C_CryptProtectedHeadersWrite
Config: Generate protected header (Memory Hole) for signed and encrypted emails.
Definition: config.c:45
+ 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 405 of file crypt.c.

406 {
407  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "signed"))
408  {
409  return SEC_NO_FLAGS;
410  }
411 
412  char *p = mutt_param_get(&b->parameter, "protocol");
413  if (!p)
414  return SEC_NO_FLAGS;
415 
416  if (mutt_istr_equal(p, "multipart/mixed"))
417  return SEC_SIGN;
418 
419  if (((WithCrypto & APPLICATION_PGP) != 0) &&
420  mutt_istr_equal(p, "application/pgp-signature"))
421  {
422  return PGP_SIGN;
423  }
424 
425  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
426  mutt_istr_equal(p, "application/x-pkcs7-signature"))
427  {
428  return SMIME_SIGN;
429  }
430  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
431  mutt_istr_equal(p, "application/pkcs7-signature"))
432  {
433  return SMIME_SIGN;
434  }
435 
436  return SEC_NO_FLAGS;
437 }
#define SMIME_SIGN
Definition: lib.h:105
#define WithCrypto
Definition: lib.h:118
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
#define PGP_SIGN
Definition: lib.h:99
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define SEC_SIGN
Email is signed.
Definition: lib.h:81
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ 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 445 of file crypt.c.

446 {
447  if ((WithCrypto & APPLICATION_PGP) == 0)
448  return SEC_NO_FLAGS;
449 
450  char *p = NULL;
451 
452  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
453  !mutt_istr_equal(b->subtype, "encrypted") ||
454  !(p = mutt_param_get(&b->parameter, "protocol")) ||
455  !mutt_istr_equal(p, "application/pgp-encrypted"))
456  {
457  return SEC_NO_FLAGS;
458  }
459 
460  return PGP_ENCRYPT;
461 }
#define WithCrypto
Definition: lib.h:118
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
#define PGP_ENCRYPT
Definition: lib.h:98
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
+ 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 469 of file crypt.c.

470 {
472  return 0;
473 
474  b = b->parts;
475  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
476  !mutt_istr_equal(b->subtype, "pgp-encrypted"))
477  {
478  return 0;
479  }
480 
481  b = b->next;
482  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
483  !mutt_istr_equal(b->subtype, "octet-stream"))
484  {
485  return 0;
486  }
487 
488  return PGP_ENCRYPT;
489 }
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
#define PGP_ENCRYPT
Definition: lib.h:98
struct Body * next
next attachment in the list
Definition: body.h:53
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:445
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;application/*&#39;.
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 506 of file crypt.c.

507 {
508  if (!(WithCrypto & APPLICATION_PGP))
509  return SEC_NO_FLAGS;
510 
511  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
512  {
513  return SEC_NO_FLAGS;
514  }
515 
516  b = b->parts;
517  if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
518  !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
519  {
520  return SEC_NO_FLAGS;
521  }
522 
523  b = b->next;
524  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
525  !mutt_istr_equal(b->subtype, "pgp-encrypted"))
526  {
527  return SEC_NO_FLAGS;
528  }
529 
530  b = b->next;
531  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
532  !mutt_istr_equal(b->subtype, "octet-stream"))
533  {
534  return SEC_NO_FLAGS;
535  }
536 
537  b = b->next;
538  if (b)
539  return SEC_NO_FLAGS;
540 
541  return PGP_ENCRYPT;
542 }
#define WithCrypto
Definition: lib.h:118
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
#define PGP_ENCRYPT
Definition: lib.h:98
struct Body * next
next attachment in the list
Definition: body.h:53
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Type: &#39;text/*&#39;.
Definition: mime.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 m)

Does the message use PGP?

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

Definition at line 550 of file crypt.c.

551 {
553  char *p = NULL;
554 
555  if (m->type == TYPE_APPLICATION)
556  {
557  if (mutt_istr_equal(m->subtype, "pgp") ||
558  mutt_istr_equal(m->subtype, "x-pgp-message"))
559  {
560  p = mutt_param_get(&m->parameter, "x-action");
561  if (p && (mutt_istr_equal(p, "sign") || mutt_istr_equal(p, "signclear")))
562  {
563  t |= PGP_SIGN;
564  }
565 
566  p = mutt_param_get(&m->parameter, "format");
567  if (p && mutt_istr_equal(p, "keys-only"))
568  {
569  t |= PGP_KEY;
570  }
571 
572  if (t == SEC_NO_FLAGS)
573  t |= PGP_ENCRYPT; /* not necessarily correct, but... */
574  }
575 
576  if (mutt_istr_equal(m->subtype, "pgp-signed"))
577  t |= PGP_SIGN;
578 
579  if (mutt_istr_equal(m->subtype, "pgp-keys"))
580  t |= PGP_KEY;
581  }
582  else if ((m->type == TYPE_TEXT) && mutt_istr_equal("plain", m->subtype))
583  {
584  if (((p = mutt_param_get(&m->parameter, "x-mutt-action")) ||
585  (p = mutt_param_get(&m->parameter, "x-action")) ||
586  (p = mutt_param_get(&m->parameter, "action"))) &&
587  mutt_istr_startswith(p, "pgp-sign"))
588  {
589  t |= PGP_SIGN;
590  }
591  else if (p && mutt_istr_startswith(p, "pgp-encrypt"))
592  t |= PGP_ENCRYPT;
593  else if (p && mutt_istr_startswith(p, "pgp-keys"))
594  t |= PGP_KEY;
595  }
596  if (t)
597  t |= PGP_INLINE;
598 
599  return t;
600 }
#define PGP_INLINE
Definition: lib.h:102
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
#define PGP_ENCRYPT
Definition: lib.h:98
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:78
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
Type: &#39;text/*&#39;.
Definition: mime.h:38
#define PGP_SIGN
Definition: lib.h:99
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define PGP_KEY
Definition: lib.h:101
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 m)

Does the message use S/MIME?

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

Definition at line 608 of file crypt.c.

609 {
610  if (!m)
611  return SEC_NO_FLAGS;
612 
613  if (((m->type & TYPE_APPLICATION) == 0) || !m->subtype)
614  return SEC_NO_FLAGS;
615 
616  char *t = NULL;
617  bool complain = false;
618  /* S/MIME MIME types don't need x- anymore, see RFC2311 */
619  if (mutt_istr_equal(m->subtype, "x-pkcs7-mime") || mutt_istr_equal(m->subtype, "pkcs7-mime"))
620  {
621  t = mutt_param_get(&m->parameter, "smime-type");
622  if (t)
623  {
624  if (mutt_istr_equal(t, "enveloped-data"))
625  return SMIME_ENCRYPT;
626  if (mutt_istr_equal(t, "signed-data"))
627  return SMIME_SIGN | SMIME_OPAQUE;
628  return SEC_NO_FLAGS;
629  }
630  /* Netscape 4.7 uses
631  * Content-Description: S/MIME Encrypted Message
632  * instead of Content-Type parameter */
633  if (mutt_istr_equal(m->description, "S/MIME Encrypted Message"))
634  return SMIME_ENCRYPT;
635  complain = true;
636  }
637  else if (!mutt_istr_equal(m->subtype, "octet-stream"))
638  return SEC_NO_FLAGS;
639 
640  t = mutt_param_get(&m->parameter, "name");
641 
642  if (!t)
643  t = m->d_filename;
644  if (!t)
645  t = m->filename;
646  if (!t)
647  {
648  if (complain)
649  {
650  mutt_message(
651  _("S/MIME messages with no hints on content are unsupported"));
652  }
653  return SEC_NO_FLAGS;
654  }
655 
656  /* no .p7c, .p10 support yet. */
657 
658  int len = mutt_str_len(t) - 4;
659  if ((len > 0) && (*(t + len) == '.'))
660  {
661  len++;
662  if (mutt_istr_equal((t + len), "p7m"))
663  {
664  /* Not sure if this is the correct thing to do, but
665  * it's required for compatibility with Outlook */
666  return SMIME_SIGN | SMIME_OPAQUE;
667  }
668  else if (mutt_istr_equal((t + len), "p7s"))
669  return SMIME_SIGN | SMIME_OPAQUE;
670  }
671 
672  return SEC_NO_FLAGS;
673 }
#define SMIME_OPAQUE
Definition: lib.h:108
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define SMIME_SIGN
Definition: lib.h:105
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
#define mutt_message(...)
Definition: logging.h:83
#define SMIME_ENCRYPT
Definition: lib.h:104
#define _(a)
Definition: message.h:28
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
char * description
content-description
Definition: body.h:40
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_query()

SecurityFlags crypt_query ( struct Body m)

Check out the type of encryption used.

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

Set the cached status values if there are any.

Definition at line 683 of file crypt.c.

684 {
685  if (!WithCrypto || !m)
686  return SEC_NO_FLAGS;
687 
689 
690  if (m->type == TYPE_APPLICATION)
691  {
693  rc |= mutt_is_application_pgp(m);
694 
696  {
697  rc |= mutt_is_application_smime(m);
698  if (rc && m->goodsig)
699  rc |= SEC_GOODSIGN;
700  if (rc && m->badsig)
701  rc |= SEC_BADSIGN;
702  }
703  }
704  else if (((WithCrypto & APPLICATION_PGP) != 0) && (m->type == TYPE_TEXT))
705  {
706  rc |= mutt_is_application_pgp(m);
707  if (rc && m->goodsig)
708  rc |= SEC_GOODSIGN;
709  }
710 
711  if (m->type == TYPE_MULTIPART)
712  {
714  rc |= mutt_is_multipart_signed(m);
716 
717  if (rc && m->goodsig)
718  rc |= SEC_GOODSIGN;
719 #ifdef USE_AUTOCRYPT
720  if (rc && m->is_autocrypt)
721  rc |= SEC_AUTOCRYPT;
722 #endif
723  }
724 
725  if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE))
726  {
727  SecurityFlags u = m->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
728  SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
729 
730  for (struct Body *b = m->parts; b; b = b->next)
731  {
732  const SecurityFlags v = crypt_query(b);
733  u &= v;
734  w |= v;
735  }
736  rc |= u | (w & ~SEC_GOODSIGN);
737 
738  if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
739  rc |= SEC_PARTSIGN;
740  }
741 
742  return rc;
743 }
#define WithCrypto
Definition: lib.h:118
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
bool is_autocrypt
Flag autocrypt-decrypted messages for replying.
Definition: body.h:79
struct Body * next
next attachment in the list
Definition: body.h:53
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:89
#define SEC_ALL_FLAGS
Definition: lib.h:96
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:78
The body of an email.
Definition: body.h:34
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:445
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:405
bool goodsig
Good cryptographic signature.
Definition: body.h:75
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:550
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
Type: &#39;text/*&#39;.
Definition: mime.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:506
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:608
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:83
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:683
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:82
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:84
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 755 of file crypt.c.

756 {
757  if (!WithCrypto)
758  return -1;
759 
760  FILE *fp = mutt_file_fopen(tempfile, "w");
761  if (!fp)
762  {
763  mutt_perror(tempfile);
764  return -1;
765  }
766 
767  fseeko(s->fp_in, a->hdr_offset, SEEK_SET);
768  size_t bytes = a->length + a->offset - a->hdr_offset;
769  bool hadcr = false;
770  while (bytes > 0)
771  {
772  const int c = fgetc(s->fp_in);
773  if (c == EOF)
774  break;
775 
776  bytes--;
777 
778  if (c == '\r')
779  hadcr = true;
780  else
781  {
782  if ((c == '\n') && !hadcr)
783  fputc('\r', fp);
784 
785  hadcr = false;
786  }
787 
788  fputc(c, fp);
789  }
790  mutt_file_fclose(&fp);
791 
792  return 0;
793 }
#define WithCrypto
Definition: lib.h:118
#define mutt_perror(...)
Definition: logging.h:85
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
FILE * fp_in
File to read from.
Definition: state.h:46
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ 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 799 of file crypt.c.

800 {
801  if (!WithCrypto)
802  return;
803 
804  while (a)
805  {
806  if (a->type == TYPE_MULTIPART)
807  {
808  if (a->encoding != ENC_7BIT)
809  {
810  a->encoding = ENC_7BIT;
812  }
813  else if (((WithCrypto & APPLICATION_PGP) != 0) && C_PgpStrictEnc)
815  }
816  else if ((a->type == TYPE_MESSAGE) &&
817  !mutt_istr_equal(a->subtype, "delivery-status"))
818  {
819  if (a->encoding != ENC_7BIT)
820  mutt_message_to_7bit(a, NULL, NeoMutt->sub);
821  }
822  else if (a->encoding == ENC_8BIT)
824  else if (a->encoding == ENC_BINARY)
825  a->encoding = ENC_BASE64;
826  else if (a->content && (a->encoding != ENC_BASE64) &&
827  (a->content->from || (a->content->space && C_PgpStrictEnc)))
828  {
830  }
831  a = a->next;
832  }
833 }
#define WithCrypto
Definition: lib.h:118
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:51
7-bit text
Definition: mime.h:49
void mutt_message_to_7bit(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:744
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:799
struct Body * next
next attachment in the list
Definition: body.h:53
8-bit text
Definition: mime.h:50
Container for Accounts, Notifications.
Definition: neomutt.h:36
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
bool C_PgpStrictEnc
Config: Encode PGP signed messages with quoted-printable (don&#39;t unset)
Definition: config.c:64
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
bool from
Has a line beginning with "From "?
Definition: content.h:43
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Binary.
Definition: mime.h:53
Quoted-printable text.
Definition: mime.h:51
bool space
Whitespace at the end of lines?
Definition: content.h:41
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_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 842 of file crypt.c.

843 {
844  if (!WithCrypto)
845  return;
846 
847  struct Buffer *tempfname = mutt_buffer_pool_get();
848  mutt_buffer_mktemp(tempfname);
849  FILE *fp_out = mutt_file_fopen(mutt_b2s(tempfname), "w");
850  if (!fp_out)
851  {
852  mutt_perror(mutt_b2s(tempfname));
853  goto cleanup;
854  }
855 
857  OptDontHandlePgpKeys = true;
858 
859  struct EmailNode *en = NULL;
860  STAILQ_FOREACH(en, el, entries)
861  {
862  struct Email *e = en->email;
863 
866  {
867  mutt_file_fclose(&fp_out);
868  break;
869  }
870 
871  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
872  {
874  fflush(fp_out);
875 
876  mutt_endwin();
877  puts(_("Trying to extract PGP keys...\n"));
878  crypt_pgp_invoke_import(mutt_b2s(tempfname));
879  }
880 
881  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
882  {
883  if (e->security & SEC_ENCRYPT)
884  {
886  CH_NO_FLAGS, 0);
887  }
888  else
890  fflush(fp_out);
891 
892  char *mbox = NULL;
893  if (!TAILQ_EMPTY(&e->env->from))
894  {
896  mbox = TAILQ_FIRST(&e->env->from)->mailbox;
897  }
898  else if (!TAILQ_EMPTY(&e->env->sender))
899  {
901  mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
902  }
903  if (mbox)
904  {
905  mutt_endwin();
906  puts(_("Trying to extract S/MIME certificates..."));
907  crypt_smime_invoke_import(mutt_b2s(tempfname), mbox);
908  }
909  }
910 
911  rewind(fp_out);
912  }
913 
914  mutt_file_fclose(&fp_out);
915  if (isendwin())
917 
918  mutt_file_unlink(mutt_b2s(tempfname));
919 
920  if (WithCrypto & APPLICATION_PGP)
921  OptDontHandlePgpKeys = false;
922 
923 cleanup:
924  mutt_buffer_pool_release(&tempfname);
925 }
#define MUTT_CM_DECODE_CRYPT
Definition: copy.h:47
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define WithCrypto
Definition: lib.h:118
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:295
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define mutt_perror(...)
Definition: logging.h:85
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:80
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:48
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:821
#define _(a)
Definition: message.h:28
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:89
WHERE bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:36
#define mutt_b2s(buf)
Definition: buffer.h:41
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:569
void crypt_pgp_invoke_import(const char *fname)
Wrapper for CryptModuleSpecs::pgp_invoke_import()
Definition: cryptglue.c:362
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:45
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:602
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import()
Definition: cryptglue.c:508
struct Email * email
Email in the list.
Definition: email.h:116
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
List of Emails.
Definition: email.h:114
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define MUTT_CM_NOHEADER
Don&#39;t copy the message header.
Definition: copy.h:35
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ 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  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;
985  self_encrypt = C_PgpDefaultKey;
986  }
987  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
988  {
989  *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
990  if (!*keylist)
991  {
992  mutt_addrlist_clear(&addrlist);
993  return -1;
994  }
996  self_encrypt = C_SmimeDefaultKey;
997  }
998  }
999 
1000  if (!oppenc_mode && self_encrypt)
1001  {
1002  const size_t keylist_size = mutt_str_len(*keylist);
1003  mutt_mem_realloc(keylist, keylist_size + mutt_str_len(self_encrypt) + 2);
1004  sprintf(*keylist + keylist_size, " %s", self_encrypt);
1005  }
1006 
1007  mutt_addrlist_clear(&addrlist);
1008 
1009  return 0;
1010 }
#define WithCrypto
Definition: lib.h:118
char * crypt_smime_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:475
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:80
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
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:89
unsigned char C_SmimeEncryptSelf
Definition: config.c:65
Container for Accounts, Notifications.
Definition: neomutt.h:36
Do no use Autocrypt.
Definition: lib.h:157
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1398
struct Envelope * env
Envelope information.
Definition: email.h:89
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: config.c:51
bool C_SmimeSelfEncrypt
Config: Encrypted messages will also be encrypt to C_SmimeDefaultKey too.
Definition: config.c:66
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
WHERE bool OptPgpCheckTrust
(pseudo) used by pgp_select_key()
Definition: options.h:49
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:54
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:314
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1179
enum AutocryptRec mutt_autocrypt_ui_recommendation(struct Email *e, char **keylist)
Get the recommended action for an Email.
Definition: autocrypt.c:550
unsigned char C_PgpEncryptSelf
Definition: config.c:60
bool C_PgpSelfEncrypt
Config: Encrypted messages will also be encrypted to C_PgpDefaultKey too.
Definition: config.c:63
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
+ 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 1019 of file crypt.c.

1020 {
1021  if (!WithCrypto)
1022  return;
1023 
1025  return;
1026 
1027  char *pgpkeylist = NULL;
1028 
1029  crypt_get_keys(e, &pgpkeylist, 1);
1030  if (pgpkeylist)
1031  {
1032  e->security |= SEC_ENCRYPT;
1033  FREE(&pgpkeylist);
1034  }
1035  else
1036  {
1037  e->security &= ~SEC_ENCRYPT;
1038  }
1039 }
#define WithCrypto
Definition: lib.h:118
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:80
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:941
bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: config.c:41
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:88
#define FREE(x)
Definition: memory.h:40
+ 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 1047 of file crypt.c.

1048 {
1049  if (!WithCrypto)
1050  return;
1051 
1052  for (; a; a = a->next)
1053  {
1054  if (a->type == TYPE_MULTIPART)
1055  crypt_fetch_signatures(signatures, a->parts, n);
1056  else
1057  {
1058  if ((*n % 5) == 0)
1059  mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1060 
1061  (*signatures)[(*n)++] = a;
1062  }
1063  }
1064 }
#define WithCrypto
Definition: lib.h:118
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1047
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
int n
Definition: acutest.h:492
+ 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
boolTrue if the subject should be protected

Definition at line 1071 of file crypt.c.

1072 {
1075  {
1076  return true;
1077  }
1078 
1079  return false;
1080 }
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:80
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:89
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:87
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: config.c:57
bool C_CryptProtectedHeadersWrite
Config: Generate protected header (Memory Hole) for signed and encrypted emails.
Definition: config.c:45
+ Here is the caller graph for this function:

◆ mutt_protected_headers_handler()

int mutt_protected_headers_handler ( struct Body a,
struct State s 
)

Process a protected header - Implements handler_t.

Definition at line 1085 of file crypt.c.

1086 {
1088  {
1089  if (a->mime_headers->subject)
1090  {
1091  const bool display = (s->flags & MUTT_DISPLAY);
1092 
1093  if (display && C_Weed && mutt_matches_ignore("subject"))
1094  return 0;
1095 
1097  int wraplen = display ? mutt_window_wrap_cols(s->wraplen, C_Wrap) : 0;
1098 
1099  mutt_write_one_header(s->fp_out, "Subject", a->mime_headers->subject, s->prefix,
1100  wraplen, display ? CH_DISPLAY : CH_NO_FLAGS, NeoMutt->sub);
1101  state_puts(s, "\n");
1102  }
1103  }
1104 
1105  return 0;
1106 }
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition: parse.c:309
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
#define state_puts(STATE, STR)
Definition: state.h:55
bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: config.c:43
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
FILE * fp_out
File to write to.
Definition: state.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:36
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int wraplen
Width to wrap lines to (when flags & MUTT_DISPLAY)
Definition: state.h:50
WHERE short C_Wrap
Config: Width to wrap text in the pager.
Definition: mutt_globals.h:119
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
Definition: mutt_window.c:473
void state_mark_protected_header(struct State *s)
Write a unique marker around protected headers.
Definition: state.c:56
char * subject
Email&#39;s subject.
Definition: envelope.h:66
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags, struct ConfigSubset *sub)
Write one header line to a file.
Definition: header.c:419
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_signed_handler()

int mutt_signed_handler ( struct Body a,
struct State s 
)

Verify a "multipart/signed" body - Implements handler_t.

Definition at line 1111 of file crypt.c.

1112 {
1113  if (!WithCrypto)
1114  return -1;
1115 
1116  bool inconsistent = false;
1117  struct Body *b = a;
1118  struct Body **signatures = NULL;
1119  int sigcnt = 0;
1120  int rc = 0;
1121  struct Buffer *tempfile = NULL;
1122 
1123  a = a->parts;
1124  SecurityFlags signed_type = mutt_is_multipart_signed(b);
1125  if (signed_type == SEC_NO_FLAGS)
1126  {
1127  /* A null protocol value is already checked for in mutt_body_handler() */
1128  state_printf(s,
1129  _("[-- Error: "
1130  "Unknown multipart/signed protocol %s --]\n\n"),
1131  mutt_param_get(&b->parameter, "protocol"));
1132  return mutt_body_handler(a, s);
1133  }
1134 
1135  if (!(a && a->next))
1136  inconsistent = true;
1137  else
1138  {
1139  switch (signed_type)
1140  {
1141  case SEC_SIGN:
1142  if ((a->next->type != TYPE_MULTIPART) || !mutt_istr_equal(a->next->subtype, "mixed"))
1143  {
1144  inconsistent = true;
1145  }
1146  break;
1147  case PGP_SIGN:
1148  if ((a->next->type != TYPE_APPLICATION) ||
1149  !mutt_istr_equal(a->next->subtype, "pgp-signature"))
1150  {
1151  inconsistent = true;
1152  }
1153  break;
1154  case SMIME_SIGN:
1155  if ((a->next->type != TYPE_APPLICATION) ||
1156  (!mutt_istr_equal(a->next->subtype, "x-pkcs7-signature") &&
1157  !mutt_istr_equal(a->next->subtype, "pkcs7-signature")))
1158  {
1159  inconsistent = true;
1160  }
1161  break;
1162  default:
1163  inconsistent = true;
1164  }
1165  }
1166  if (inconsistent)
1167  {
1168  state_attach_puts(s, _("[-- Error: Missing or bad-format multipart/signed "
1169  "signature --]\n\n"));
1170  return mutt_body_handler(a, s);
1171  }
1172 
1173  if (s->flags & MUTT_DISPLAY)
1174  {
1175  crypt_fetch_signatures(&signatures, a->next, &sigcnt);
1176 
1177  if (sigcnt != 0)
1178  {
1179  tempfile = mutt_buffer_pool_get();
1180  mutt_buffer_mktemp(tempfile);
1181  bool goodsig = true;
1182  if (crypt_write_signed(a, s, mutt_b2s(tempfile)) == 0)
1183  {
1184  for (int i = 0; i < sigcnt; i++)
1185  {
1186  if (((WithCrypto & APPLICATION_PGP) != 0) &&
1187  (signatures[i]->type == TYPE_APPLICATION) &&
1188  mutt_istr_equal(signatures[i]->subtype, "pgp-signature"))
1189  {
1190  if (crypt_pgp_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1191  goodsig = false;
1192 
1193  continue;
1194  }
1195 
1196  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1197  (signatures[i]->type == TYPE_APPLICATION) &&
1198  (mutt_istr_equal(signatures[i]->subtype, "x-pkcs7-signature") ||
1199  mutt_istr_equal(signatures[i]->subtype, "pkcs7-signature")))
1200  {
1201  if (crypt_smime_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1202  goodsig = false;
1203 
1204  continue;
1205  }
1206 
1207  state_printf(s,
1208  _("[-- Warning: "
1209  "We can't verify %s/%s signatures. --]\n\n"),
1210  TYPE(signatures[i]), signatures[i]->subtype);
1211  }
1212  }
1213 
1214  mutt_file_unlink(mutt_b2s(tempfile));
1215  mutt_buffer_pool_release(&tempfile);
1216 
1217  b->goodsig = goodsig;
1218  b->badsig = !goodsig;
1219 
1220  /* Now display the signed body */
1221  state_attach_puts(s, _("[-- The following data is signed --]\n\n"));
1222 
1224 
1225  FREE(&signatures);
1226  }
1227  else
1228  {
1230  _("[-- Warning: Can't find any signatures. --]\n\n"));
1231  }
1232  }
1233 
1234  rc = mutt_body_handler(a, s);
1235 
1236  if ((s->flags & MUTT_DISPLAY) && (sigcnt != 0))
1237  state_attach_puts(s, _("\n[-- End of signed data --]\n"));
1238 
1239  return rc;
1240 }
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1085
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:153
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define SMIME_SIGN
Definition: lib.h:105
#define WithCrypto
Definition: lib.h:118
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:79
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:78
int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
Write the message body/part.
Definition: crypt.c:755
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:405
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
char * subtype
content-type subtype
Definition: body.h:37
#define mutt_b2s(buf)
Definition: buffer.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:75
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:93
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:92
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define PGP_SIGN
Definition: lib.h:99
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1047
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define SEC_SIGN
Email is signed.
Definition: lib.h:81
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
#define TYPE(body)
Definition: mime.h:83
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
int crypt_smime_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:517
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1585
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
Type: &#39;application/*&#39;.
Definition: mime.h:33
int crypt_pgp_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:371
+ 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 1256 of file crypt.c.

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

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

Definition at line 1345 of file crypt.c.

1346 {
1347  /* or should we require the "0x"? */
1348  if (mutt_strn_equal(s, "0x", 2))
1349  s += 2;
1350  if (strlen(s) % 8)
1351  return false;
1352  while (*s)
1353  if (!strchr("0123456789ABCDEFabcdef", *s++))
1354  return false;
1355 
1356  return true;
1357 }
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:598
+ Here is the call graph for this function:
+ Here is the caller graph for this function: