NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 "globals.h"
#include "handler.h"
#include "mx.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 *state, const char *app_name)
 Print the current time.
 
void crypt_forget_passphrase (void)
 Forget a passphrase and display a message.
 
bool crypt_valid_passphrase (SecurityFlags flags)
 Check that we have a usable passphrase, ask if not.
 
int mutt_protect (struct Email *e, char *keylist, bool postpone)
 Encrypt and/or sign a message.
 
SecurityFlags mutt_is_multipart_signed (struct Body *b)
 Is a message signed?
 
SecurityFlags mutt_is_multipart_encrypted (struct Body *b)
 Does the message have encrypted parts?
 
int mutt_is_valid_multipart_pgp_encrypted (struct Body *b)
 Is this a valid multi-part encrypted message?
 
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted (struct Body *b)
 Check for malformed layout.
 
SecurityFlags mutt_is_application_pgp (struct Body *b)
 Does the message use PGP?
 
SecurityFlags mutt_is_application_smime (struct Body *b)
 Does the message use S/MIME?
 
SecurityFlags crypt_query (struct Body *b)
 Check out the type of encryption used.
 
int crypt_write_signed (struct Body *a, struct State *state, const char *tempfile)
 Write the message body/part.
 
void crypt_convert_to_7bit (struct Body *a)
 Convert an email to 7bit encoding.
 
void crypt_extract_keys_from_messages (struct Mailbox *m, struct EmailArray *ea)
 Extract keys from a message.
 
int crypt_get_keys (struct Email *e, char **keylist, bool oppenc_mode)
 Check we have all the keys we need.
 
void crypt_opportunistic_encrypt (struct Email *e)
 Can all recipients be determined.
 
static void crypt_fetch_signatures (struct Body ***signatures, struct Body *a, int *n)
 Create an array of an emails parts.
 
bool mutt_should_hide_protected_subject (struct Email *e)
 Should NeoMutt hide the protected subject?
 
int mutt_protected_headers_handler (struct Body *b, struct State *state)
 Process a protected header - Implements handler_t -.
 
int mutt_signed_handler (struct Body *b, struct State *state)
 Verify a "multipart/signed" body - Implements handler_t -.
 
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.
 
bool crypt_is_numerical_keyid (const char *s)
 Is this a numerical keyid.
 

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 state,
const char *  app_name 
)

Print the current time.

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

print the current time to avoid spoofing of the signature output

Definition at line 69 of file crypt.c.

70{
71 char p[256], tmp[256];
72
73 if (!WithCrypto)
74 return;
75
76 const bool c_crypt_timestamp = cs_subset_bool(NeoMutt->sub, "crypt_timestamp");
77 if (c_crypt_timestamp)
78 {
79 mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), mutt_date_now());
80 }
81 else
82 {
83 *p = '\0';
84 }
85
86 snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
87 state_attach_puts(state, tmp);
88}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:924
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:446
#define _(a)
Definition: message.h:28
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
Definition: state.c:102
#define WithCrypto
Definition: lib.h:117
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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 93 of file crypt.c.

94{
97
100
101 if (WithCrypto)
102 {
103 /* L10N: Due to the implementation details (e.g. some passwords are managed
104 by gpg-agent) we can't know whether we forgot zero, 1, 12, ...
105 passwords. So in English we use "Passphrases". Your language might
106 have other means to express this. */
107 mutt_message(_("Passphrases forgotten"));
108 }
109}
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: logging2.h:91
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:91
#define APPLICATION_SMIME
Use SMIME 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 135 of file crypt.c.

136{
137 bool rc = false;
138
139#ifndef DEBUG
140 disable_coredumps();
141#endif
142
143 if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & APPLICATION_PGP))
145
146 if (((WithCrypto & APPLICATION_SMIME) != 0) && (flags & APPLICATION_SMIME))
148
149 return rc;
150}
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 160 of file crypt.c.

161{
162 struct Body *pbody = NULL, *tmp_pbody = NULL;
163 struct Body *tmp_smime_pbody = NULL;
164 struct Body *tmp_pgp_pbody = NULL;
165 bool has_retainable_sig = false;
166
167 if (!WithCrypto)
168 return -1;
169
170 SecurityFlags security = e->security;
171 int sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
172 if (postpone)
173 {
174 sign = SEC_NO_FLAGS;
175 security &= ~SEC_SIGN;
176 }
177
178 if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
179 return 0;
180
181 if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
182 return -1;
183
184 if (((WithCrypto & APPLICATION_PGP) != 0) && !(security & SEC_AUTOCRYPT) &&
185 ((security & PGP_INLINE) == PGP_INLINE))
186 {
187 if ((e->body->type != TYPE_TEXT) || !mutt_istr_equal(e->body->subtype, "plain"))
188 {
189 if (query_quadoption(_("Inline PGP can't be used with attachments. Revert to PGP/MIME?"),
190 NeoMutt->sub, "pgp_mime_auto") != 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(_("Inline PGP can't be used with format=flowed. Revert to PGP/MIME?"),
199 NeoMutt->sub, "pgp_mime_auto")) != 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(_("Message can't be sent inline. Revert to using PGP/MIME?"),
222 NeoMutt->sub, "pgp_mime_auto") != 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;
256 }
257
258 mailbox = buf_string(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 = buf_string(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
331 if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
332 {
333 if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
334 {
335 tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
336 if (!tmp_pbody)
337 {
338 /* signed ? free it! */
339 goto bail;
340 }
341 /* free tmp_body if messages was signed AND encrypted ... */
342 if ((tmp_smime_pbody != e->body) && (tmp_smime_pbody != tmp_pbody))
343 {
344 /* detach and don't delete e->body,
345 * which tmp_smime_pbody->parts after signing. */
346 tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
347 e->body->next = NULL;
348 mutt_body_free(&tmp_smime_pbody);
349 }
350 pbody = tmp_pbody;
351 }
352
353 if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
354 {
355 pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
356 if (!pbody)
357 {
358 /* did we perform a retainable signature? */
359 if (has_retainable_sig)
360 {
361 /* remove the outer multipart layer */
362 tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
363 /* get rid of the signature */
364 mutt_body_free(&tmp_pgp_pbody->next);
365 }
366
367 goto bail;
368 }
369
370 // destroy temporary signature envelope when doing retainable signatures.
371 if (has_retainable_sig)
372 {
373 tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
374 mutt_body_free(&tmp_pgp_pbody->next);
375 }
376 }
377 }
378
379 if (pbody)
380 {
381 e->body = pbody;
382 return 0;
383 }
384
385bail:
387 mutt_param_delete(&e->body->parameter, "protected-headers");
388 return -1;
389}
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:460
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:823
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: config_type.c:262
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
struct Body * crypt_pgp_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:327
struct Body * crypt_smime_build_smime_entity(struct Body *a, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:497
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_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_pgp_traditional_encryptsign(struct Body *a, SecurityFlags flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:294
struct Body * crypt_smime_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:486
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:154
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: logging2.h:92
@ 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:810
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:88
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:77
#define PGP_INLINE
Definition: lib.h:101
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:78
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:79
#define SEC_SIGN
Email is signed.
Definition: lib.h:80
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
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition: question.c:369
#define TAILQ_FIRST(head)
Definition: queue.h:723
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition: send.c:1463
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:778
An email address.
Definition: address.h:36
struct Buffer * 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 397 of file crypt.c.

398{
399 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "signed"))
400 {
401 return SEC_NO_FLAGS;
402 }
403
404 char *p = mutt_param_get(&b->parameter, "protocol");
405 if (!p)
406 return SEC_NO_FLAGS;
407
408 if (mutt_istr_equal(p, "multipart/mixed"))
409 return SEC_SIGN;
410
411 if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_istr_equal(p, "application/pgp-signature"))
412 {
413 return PGP_SIGN;
414 }
415
416 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
417 (mutt_istr_equal(p, "application/x-pkcs7-signature") ||
418 mutt_istr_equal(p, "application/pkcs7-signature")))
419 {
420 return SMIME_SIGN;
421 }
422
423 return SEC_NO_FLAGS;
424}
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
#define PGP_SIGN
Definition: lib.h:98
#define SMIME_SIGN
Definition: lib.h:104
+ 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 432 of file crypt.c.

433{
434 if ((WithCrypto & APPLICATION_PGP) == 0)
435 return SEC_NO_FLAGS;
436
437 char *p = NULL;
438
439 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
440 !mutt_istr_equal(b->subtype, "encrypted") ||
441 !(p = mutt_param_get(&b->parameter, "protocol")) ||
442 !mutt_istr_equal(p, "application/pgp-encrypted"))
443 {
444 return SEC_NO_FLAGS;
445 }
446
447 return PGP_ENCRYPT;
448}
#define PGP_ENCRYPT
Definition: lib.h:97
+ 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 456 of file crypt.c.

457{
459 return 0;
460
461 b = b->parts;
462 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
463 !mutt_istr_equal(b->subtype, "pgp-encrypted"))
464 {
465 return 0;
466 }
467
468 b = b->next;
469 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
470 !mutt_istr_equal(b->subtype, "octet-stream"))
471 {
472 return 0;
473 }
474
475 return PGP_ENCRYPT;
476}
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:432
@ 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 493 of file crypt.c.

494{
496 return SEC_NO_FLAGS;
497
498 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
499 {
500 return SEC_NO_FLAGS;
501 }
502
503 b = b->parts;
504 if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
505 !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
506 {
507 return SEC_NO_FLAGS;
508 }
509
510 b = b->next;
511 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
512 !mutt_istr_equal(b->subtype, "pgp-encrypted"))
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, "octet-stream"))
520 {
521 return SEC_NO_FLAGS;
522 }
523
524 b = b->next;
525 if (b)
526 return SEC_NO_FLAGS;
527
528 return PGP_ENCRYPT;
529}
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 537 of file crypt.c.

538{
540 char *p = NULL;
541
542 if (b->type == TYPE_APPLICATION)
543 {
544 if (mutt_istr_equal(b->subtype, "pgp") || mutt_istr_equal(b->subtype, "x-pgp-message"))
545 {
546 p = mutt_param_get(&b->parameter, "x-action");
547 if (p && (mutt_istr_equal(p, "sign") || mutt_istr_equal(p, "signclear")))
548 {
549 t |= PGP_SIGN;
550 }
551
552 p = mutt_param_get(&b->parameter, "format");
553 if (p && mutt_istr_equal(p, "keys-only"))
554 {
555 t |= PGP_KEY;
556 }
557
558 if (t == SEC_NO_FLAGS)
559 t |= PGP_ENCRYPT; /* not necessarily correct, but... */
560 }
561
562 if (mutt_istr_equal(b->subtype, "pgp-signed"))
563 t |= PGP_SIGN;
564
565 if (mutt_istr_equal(b->subtype, "pgp-keys"))
566 t |= PGP_KEY;
567 }
568 else if ((b->type == TYPE_TEXT) && mutt_istr_equal("plain", b->subtype))
569 {
570 if (((p = mutt_param_get(&b->parameter, "x-mutt-action")) ||
571 (p = mutt_param_get(&b->parameter, "x-action")) ||
572 (p = mutt_param_get(&b->parameter, "action"))) &&
573 mutt_istr_startswith(p, "pgp-sign"))
574 {
575 t |= PGP_SIGN;
576 }
577 else if (p && mutt_istr_startswith(p, "pgp-encrypt"))
578 {
579 t |= PGP_ENCRYPT;
580 }
581 else if (p && mutt_istr_startswith(p, "pgp-keys"))
582 {
583 t |= PGP_KEY;
584 }
585 }
586 if (t)
587 t |= PGP_INLINE;
588
589 return t;
590}
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:240
#define PGP_KEY
Definition: lib.h:100
+ 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 598 of file crypt.c.

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

677{
678 if (!WithCrypto || !b)
679 return SEC_NO_FLAGS;
680
682
683 if (b->type == TYPE_APPLICATION)
684 {
687
689 {
691 if (rc && b->goodsig)
692 rc |= SEC_GOODSIGN;
693 if (rc && b->badsig)
694 rc |= SEC_BADSIGN;
695 }
696 }
697 else if (((WithCrypto & APPLICATION_PGP) != 0) && (b->type == TYPE_TEXT))
698 {
700 if (rc && b->goodsig)
701 rc |= SEC_GOODSIGN;
702 }
703
704 if (b->type == TYPE_MULTIPART)
705 {
709
710 if (rc && b->goodsig)
711 rc |= SEC_GOODSIGN;
712#ifdef USE_AUTOCRYPT
713 if (rc && b->is_autocrypt)
714 rc |= SEC_AUTOCRYPT;
715#endif
716 }
717
718 if ((b->type == TYPE_MULTIPART) || (b->type == TYPE_MESSAGE))
719 {
720 SecurityFlags u = b->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
721 SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
722
723 for (b = b->parts; b; b = b->next)
724 {
725 const SecurityFlags v = crypt_query(b);
726 u &= v;
727 w |= v;
728 }
729 rc |= u | (w & ~SEC_GOODSIGN);
730
731 if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
732 rc |= SEC_PARTSIGN;
733 }
734
735 return rc;
736}
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:537
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:397
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:598
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:493
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:676
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
#define SEC_ALL_FLAGS
Definition: lib.h:95
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:81
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:82
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:83
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 state,
const char *  tempfile 
)

Write the message body/part.

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

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

Definition at line 748 of file crypt.c.

749{
750 if (!WithCrypto)
751 return -1;
752
753 FILE *fp = mutt_file_fopen(tempfile, "w");
754 if (!fp)
755 {
756 mutt_perror("%s", tempfile);
757 return -1;
758 }
759
760 if (!mutt_file_seek(state->fp_in, a->hdr_offset, SEEK_SET))
761 {
762 mutt_file_fclose(&fp);
763 return -1;
764 }
765 size_t bytes = a->length + a->offset - a->hdr_offset;
766 bool hadcr = false;
767 while (bytes > 0)
768 {
769 const int c = fgetc(state->fp_in);
770 if (c == EOF)
771 break;
772
773 bytes--;
774
775 if (c == '\r')
776 {
777 hadcr = true;
778 }
779 else
780 {
781 if ((c == '\n') && !hadcr)
782 fputc('\r', fp);
783
784 hadcr = false;
785 }
786
787 fputc(c, fp);
788 }
789 mutt_file_fclose(&fp);
790
791 return 0;
792}
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:636
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:733
#define mutt_perror(...)
Definition: logging2.h:93
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:48
+ 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 798 of file crypt.c.

799{
800 if (!WithCrypto)
801 return;
802
803 const bool c_pgp_strict_enc = cs_subset_bool(NeoMutt->sub, "pgp_strict_enc");
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_pgp_strict_enc)
814 {
816 }
817 }
818 else if ((a->type == TYPE_MESSAGE) && !mutt_istr_equal(a->subtype, "delivery-status"))
819 {
820 if (a->encoding != ENC_7BIT)
822 }
823 else if (a->encoding == ENC_8BIT)
824 {
826 }
827 else if (a->encoding == ENC_BINARY)
828 {
829 a->encoding = ENC_BASE64;
830 }
831 else if (a->content && (a->encoding != ENC_BASE64) &&
832 (a->content->from || (a->content->space && c_pgp_strict_enc)))
833 {
835 }
836 a = a->next;
837 }
838}
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:798
@ 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:257
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 EmailArray *  ea 
)

Extract keys from a message.

Parameters
mMailbox
eaArray of Emails to process

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

Definition at line 847 of file crypt.c.

848{
849 if (!WithCrypto)
850 return;
851
852 struct Buffer *tempfname = buf_pool_get();
853 buf_mktemp(tempfname);
854 FILE *fp_out = mutt_file_fopen(buf_string(tempfname), "w");
855 if (!fp_out)
856 {
857 mutt_perror("%s", buf_string(tempfname));
858 goto cleanup;
859 }
860
863
864 struct Email **ep = NULL;
865 ARRAY_FOREACH(ep, ea)
866 {
867 struct Email *e = *ep;
868 struct Message *msg = mx_msg_open(m, e);
869 if (!msg)
870 {
871 continue;
872 }
875 {
876 mx_msg_close(m, &msg);
877 mutt_file_fclose(&fp_out);
878 break;
879 }
880
881 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
882 {
884 fflush(fp_out);
885
886 mutt_endwin();
887 puts(_("Trying to extract PGP keys...\n"));
889 }
890
892 {
893 const bool encrypt = e->security & SEC_ENCRYPT;
894 mutt_copy_message(fp_out, e, msg,
897 CH_NO_FLAGS, 0);
898 fflush(fp_out);
899
900 const char *mbox = NULL;
901 if (!TAILQ_EMPTY(&e->env->from))
902 {
904 mbox = buf_string(TAILQ_FIRST(&e->env->from)->mailbox);
905 }
906 else if (!TAILQ_EMPTY(&e->env->sender))
907 {
909 mbox = buf_string(TAILQ_FIRST(&e->env->sender)->mailbox);
910 }
911 if (mbox)
912 {
913 mutt_endwin();
914 puts(_("Trying to extract S/MIME certificates..."));
915 crypt_smime_invoke_import(buf_string(tempfname), mbox);
916 }
917 }
918 mx_msg_close(m, &msg);
919
920 rewind(fp_out);
921 }
922
923 mutt_file_fclose(&fp_out);
924 if (isendwin())
926
927 mutt_file_unlink(buf_string(tempfname));
928
930 OptDontHandlePgpKeys = false;
931
932cleanup:
933 buf_pool_release(&tempfname);
934}
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:298
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:596
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:884
#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:188
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:196
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: globals.c:69
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1206
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1160
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define TAILQ_EMPTY(head)
Definition: queue.h:721
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
struct AddressList sender
Email's sender.
Definition: envelope.h:63
A local copy of an email.
Definition: message.h:34
FILE * fp
pointer to the message data
Definition: message.h:35
#define buf_mktemp(buf)
Definition: tmp.h:33
+ 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 950 of file crypt.c.

951{
952 if (!WithCrypto)
953 return 0;
954
955 struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
956 const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
957 const char *self_encrypt = NULL;
958
959 /* Do a quick check to make sure that we can find all of the encryption
960 * keys if the user has requested this service. */
961
962 *keylist = NULL;
963
964#ifdef USE_AUTOCRYPT
965 if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
966 {
968 return -1;
969 return 0;
970 }
971#endif
972
974 OptPgpCheckTrust = true;
975
976 mutt_addrlist_copy(&addrlist, &e->env->to, false);
977 mutt_addrlist_copy(&addrlist, &e->env->cc, false);
978 mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
979 mutt_addrlist_qualify(&addrlist, fqdn);
980 mutt_addrlist_dedupe(&addrlist);
981
982 if (oppenc_mode || (e->security & SEC_ENCRYPT))
983 {
984 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
985 {
986 *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
987 if (!*keylist)
988 {
989 mutt_addrlist_clear(&addrlist);
990 return -1;
991 }
992 OptPgpCheckTrust = false;
993 const bool c_pgp_self_encrypt = cs_subset_bool(NeoMutt->sub, "pgp_self_encrypt");
994 const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
995 const enum QuadOption c_pgp_encrypt_self = cs_subset_quad(NeoMutt->sub, "pgp_encrypt_self");
996 if (c_pgp_self_encrypt || (c_pgp_encrypt_self == MUTT_YES))
997 self_encrypt = c_pgp_default_key;
998 }
1000 {
1001 *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
1002 if (!*keylist)
1003 {
1004 mutt_addrlist_clear(&addrlist);
1005 return -1;
1006 }
1007 const bool c_smime_self_encrypt = cs_subset_bool(NeoMutt->sub, "smime_self_encrypt");
1008 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
1009 const enum QuadOption c_smime_encrypt_self = cs_subset_quad(NeoMutt->sub, "smime_encrypt_self");
1010 if (c_smime_self_encrypt || (c_smime_encrypt_self == MUTT_YES))
1011 self_encrypt = c_smime_default_key;
1012 }
1013 }
1014
1015 if (!oppenc_mode && self_encrypt)
1016 {
1017 const size_t keylist_size = mutt_str_len(*keylist);
1018 mutt_mem_realloc(keylist, keylist_size + mutt_str_len(self_encrypt) + 2);
1019 sprintf(*keylist + keylist_size, " %s", self_encrypt);
1020 }
1021
1022 mutt_addrlist_clear(&addrlist);
1023
1024 return 0;
1025}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:762
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:677
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1398
@ 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:558
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:193
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
bool OptPgpCheckTrust
(pseudo) used by dlg_pgp()
Definition: globals.c:80
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
#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:705
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 1034 of file crypt.c.

1035{
1036 if (!WithCrypto)
1037 return;
1038
1039 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
1040 if (!(c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT)))
1041 return;
1042
1043 char *pgpkeylist = NULL;
1044
1045 crypt_get_keys(e, &pgpkeylist, 1);
1046 if (pgpkeylist)
1047 {
1048 e->security |= SEC_ENCRYPT;
1049 FREE(&pgpkeylist);
1050 }
1051 else
1052 {
1053 e->security &= ~SEC_ENCRYPT;
1054 }
1055}
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:950
#define FREE(x)
Definition: memory.h:45
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:87
+ 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 1063 of file crypt.c.

1064{
1065 if (!WithCrypto)
1066 return;
1067
1068 for (; a; a = a->next)
1069 {
1070 if (a->type == TYPE_MULTIPART)
1071 {
1072 crypt_fetch_signatures(signatures, a->parts, n);
1073 }
1074 else
1075 {
1076 if ((*n % 5) == 0)
1077 mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1078
1079 (*signatures)[(*n)++] = a;
1080 }
1081 }
1082}
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1063
+ 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 1089 of file crypt.c.

1090{
1091 const bool c_crypt_protected_headers_write = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_write");
1092 const char *const c_crypt_protected_headers_subject =
1093 cs_subset_string(NeoMutt->sub, "crypt_protected_headers_subject");
1094 if (c_crypt_protected_headers_write && (e->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) &&
1095 !(e->security & SEC_INLINE) && c_crypt_protected_headers_subject)
1096 {
1097 return true;
1098 }
1099
1100 return false;
1101}
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:86
+ 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 1277 of file crypt.c.

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

1367{
1368 /* or should we require the "0x"? */
1369 if (mutt_strn_equal(s, "0x", 2))
1370 s += 2;
1371 if (strlen(s) % 8)
1372 return false;
1373 while (*s)
1374 if (!strchr("0123456789ABCDEFabcdef", *s++))
1375 return false;
1376
1377 return true;
1378}
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:497
+ Here is the call graph for this function:
+ Here is the caller graph for this function: