NeoMutt  2023-03-22-27-g3cb248
Teaching an old dog new tricks
DOXYGEN
crypt.c File Reference

Signing/encryption multiplexor. More...

#include "config.h"
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "crypt.h"
#include "lib.h"
#include "attach/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "cryptglue.h"
#include "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. More...
 
void crypt_forget_passphrase (void)
 Forget a passphrase and display a message. More...
 
bool crypt_valid_passphrase (SecurityFlags flags)
 Check that we have a usable passphrase, ask if not. More...
 
int mutt_protect (struct Email *e, char *keylist, bool postpone)
 Encrypt and/or sign a message. More...
 
SecurityFlags mutt_is_multipart_signed (struct Body *b)
 Is a message signed? More...
 
SecurityFlags mutt_is_multipart_encrypted (struct Body *b)
 Does the message have encrypted parts? More...
 
int mutt_is_valid_multipart_pgp_encrypted (struct Body *b)
 Is this a valid multi-part encrypted message? More...
 
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted (struct Body *b)
 Check for malformed layout. More...
 
SecurityFlags mutt_is_application_pgp (struct Body *b)
 Does the message use PGP? More...
 
SecurityFlags mutt_is_application_smime (struct Body *b)
 Does the message use S/MIME? More...
 
SecurityFlags crypt_query (struct Body *b)
 Check out the type of encryption used. More...
 
int crypt_write_signed (struct Body *a, struct State *state, const char *tempfile)
 Write the message body/part. More...
 
void crypt_convert_to_7bit (struct Body *a)
 Convert an email to 7bit encoding. More...
 
void crypt_extract_keys_from_messages (struct Mailbox *m, struct EmailList *el)
 Extract keys from a message. More...
 
int crypt_get_keys (struct Email *e, char **keylist, bool oppenc_mode)
 Check we have all the keys we need. More...
 
void crypt_opportunistic_encrypt (struct Email *e)
 Can all recipients be determined. More...
 
static void crypt_fetch_signatures (struct Body ***signatures, struct Body *a, int *n)
 Create an array of an emails parts. More...
 
bool mutt_should_hide_protected_subject (struct Email *e)
 Should NeoMutt hide the protected subject? More...
 
int mutt_protected_headers_handler (struct Body *b, struct State *state)
 Process a protected header - Implements handler_t -. More...
 
int mutt_signed_handler (struct Body *b, struct State *state)
 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 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 *p = '\0';
83
84 snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
85 state_attach_puts(state, tmp);
86}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:702
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:432
#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:116
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_forget_passphrase()

void crypt_forget_passphrase ( void  )

Forget a passphrase and display a message.

Definition at line 91 of file crypt.c.

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

◆ crypt_valid_passphrase()

bool crypt_valid_passphrase ( SecurityFlags  flags)

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

Parameters
flagsFlags, see SecurityFlags
Return values
trueSuccess
falseFailed

Definition at line 133 of file crypt.c.

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

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

◆ mutt_is_multipart_signed()

SecurityFlags mutt_is_multipart_signed ( struct Body b)

Is a message signed?

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

Definition at line 401 of file crypt.c.

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

◆ mutt_is_multipart_encrypted()

SecurityFlags mutt_is_multipart_encrypted ( struct Body b)

Does the message have encrypted parts?

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

Definition at line 436 of file crypt.c.

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

◆ mutt_is_valid_multipart_pgp_encrypted()

int mutt_is_valid_multipart_pgp_encrypted ( struct Body b)

Is this a valid multi-part encrypted message?

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

Definition at line 460 of file crypt.c.

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

498{
500 return SEC_NO_FLAGS;
501
502 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
503 {
504 return SEC_NO_FLAGS;
505 }
506
507 b = b->parts;
508 if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
509 !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
510 {
511 return SEC_NO_FLAGS;
512 }
513
514 b = b->next;
515 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
516 !mutt_istr_equal(b->subtype, "pgp-encrypted"))
517 {
518 return SEC_NO_FLAGS;
519 }
520
521 b = b->next;
522 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
523 !mutt_istr_equal(b->subtype, "octet-stream"))
524 {
525 return SEC_NO_FLAGS;
526 }
527
528 b = b->next;
529 if (b)
530 return SEC_NO_FLAGS;
531
532 return PGP_ENCRYPT;
533}
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 541 of file crypt.c.

542{
544 char *p = NULL;
545
546 if (b->type == TYPE_APPLICATION)
547 {
548 if (mutt_istr_equal(b->subtype, "pgp") || mutt_istr_equal(b->subtype, "x-pgp-message"))
549 {
550 p = mutt_param_get(&b->parameter, "x-action");
551 if (p && (mutt_istr_equal(p, "sign") || mutt_istr_equal(p, "signclear")))
552 {
553 t |= PGP_SIGN;
554 }
555
556 p = mutt_param_get(&b->parameter, "format");
557 if (p && mutt_istr_equal(p, "keys-only"))
558 {
559 t |= PGP_KEY;
560 }
561
562 if (t == SEC_NO_FLAGS)
563 t |= PGP_ENCRYPT; /* not necessarily correct, but... */
564 }
565
566 if (mutt_istr_equal(b->subtype, "pgp-signed"))
567 t |= PGP_SIGN;
568
569 if (mutt_istr_equal(b->subtype, "pgp-keys"))
570 t |= PGP_KEY;
571 }
572 else if ((b->type == TYPE_TEXT) && mutt_istr_equal("plain", b->subtype))
573 {
574 if (((p = mutt_param_get(&b->parameter, "x-mutt-action")) ||
575 (p = mutt_param_get(&b->parameter, "x-action")) ||
576 (p = mutt_param_get(&b->parameter, "action"))) &&
577 mutt_istr_startswith(p, "pgp-sign"))
578 {
579 t |= PGP_SIGN;
580 }
581 else if (p && mutt_istr_startswith(p, "pgp-encrypt"))
582 t |= PGP_ENCRYPT;
583 else if (p && mutt_istr_startswith(p, "pgp-keys"))
584 t |= PGP_KEY;
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:239
#define PGP_KEY
Definition: lib.h:99
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_application_smime()

SecurityFlags mutt_is_application_smime ( struct Body b)

Does the message use S/MIME?

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

Definition at line 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 return SEC_NO_FLAGS;
629
630 t = mutt_param_get(&b->parameter, "name");
631
632 if (!t)
633 t = b->d_filename;
634 if (!t)
635 t = b->filename;
636 if (!t)
637 {
638 if (complain)
639 {
640 mutt_message(_("S/MIME messages with no hints on content are unsupported"));
641 }
642 return SEC_NO_FLAGS;
643 }
644
645 /* no .p7c, .p10 support yet. */
646
647 int len = mutt_str_len(t) - 4;
648 if ((len > 0) && (*(t + len) == '.'))
649 {
650 len++;
651 if (mutt_istr_equal((t + len), "p7m"))
652 {
653 /* Not sure if this is the correct thing to do, but
654 * it's required for compatibility with Outlook */
655 return SMIME_SIGN | SMIME_OPAQUE;
656 }
657 else if (mutt_istr_equal((t + len), "p7s"))
658 return SMIME_SIGN | SMIME_OPAQUE;
659 }
660
661 return SEC_NO_FLAGS;
662}
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
#define SMIME_OPAQUE
Definition: lib.h:106
#define SMIME_ENCRYPT
Definition: lib.h:102
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
char * description
content-description
Definition: body.h:55
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_query()

SecurityFlags crypt_query ( struct Body b)

Check out the type of encryption used.

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

Set the cached status values if there are any.

Definition at line 672 of file crypt.c.

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

◆ crypt_write_signed()

int crypt_write_signed ( struct Body a,
struct State 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 744 of file crypt.c.

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

795{
796 if (!WithCrypto)
797 return;
798
799 const bool c_pgp_strict_enc = cs_subset_bool(NeoMutt->sub, "pgp_strict_enc");
800 while (a)
801 {
802 if (a->type == TYPE_MULTIPART)
803 {
804 if (a->encoding != ENC_7BIT)
805 {
806 a->encoding = ENC_7BIT;
808 }
809 else if (((WithCrypto & APPLICATION_PGP) != 0) && c_pgp_strict_enc)
811 }
812 else if ((a->type == TYPE_MESSAGE) && !mutt_istr_equal(a->subtype, "delivery-status"))
813 {
814 if (a->encoding != ENC_7BIT)
816 }
817 else if (a->encoding == ENC_8BIT)
819 else if (a->encoding == ENC_BINARY)
820 a->encoding = ENC_BASE64;
821 else if (a->content && (a->encoding != ENC_BASE64) &&
822 (a->content->from || (a->content->space && c_pgp_strict_enc)))
823 {
825 }
826 a = a->next;
827 }
828}
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:794
@ 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:252
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:69
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
bool space
Whitespace at the end of lines?
Definition: content.h:42
bool from
Has a line beginning with "From "?
Definition: content.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_extract_keys_from_messages()

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

Extract keys from a message.

Parameters
mMailbox
elList of Emails to process

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

Definition at line 837 of file crypt.c.

838{
839 if (!WithCrypto)
840 return;
841
842 struct Buffer *tempfname = mutt_buffer_pool_get();
843 mutt_buffer_mktemp(tempfname);
844 FILE *fp_out = mutt_file_fopen(mutt_buffer_string(tempfname), "w");
845 if (!fp_out)
846 {
848 goto cleanup;
849 }
850
853
854 struct EmailNode *en = NULL;
855 STAILQ_FOREACH(en, el, entries)
856 {
857 struct Email *e = en->email;
858 struct Message *msg = mx_msg_open(m, e->msgno);
859 if (!msg)
860 {
861 continue;
862 }
865 {
866 mx_msg_close(m, &msg);
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"));
879 }
880
882 {
883 const bool encrypt = e->security & SEC_ENCRYPT;
884 mutt_copy_message(fp_out, e, msg,
887 CH_NO_FLAGS, 0);
888 fflush(fp_out);
889
890 char *mbox = NULL;
891 if (!TAILQ_EMPTY(&e->env->from))
892 {
894 mbox = TAILQ_FIRST(&e->env->from)->mailbox;
895 }
896 else if (!TAILQ_EMPTY(&e->env->sender))
897 {
899 mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
900 }
901 if (mbox)
902 {
903 mutt_endwin();
904 puts(_("Trying to extract S/MIME certificates..."));
906 }
907 }
908 mx_msg_close(m, &msg);
909
910 rewind(fp_out);
911 }
912
913 mutt_file_fclose(&fp_out);
914 if (isendwin())
916
918
920 OptDontHandlePgpKeys = false;
921
922cleanup:
923 mutt_buffer_pool_release(&tempfname);
924}
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:298
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:592
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
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:875
#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:386
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:193
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: globals.c:69
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1200
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1154
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define TAILQ_EMPTY(head)
Definition: queue.h:721
String manipulation buffer.
Definition: buffer.h:34
List of Emails.
Definition: email.h:131
struct Email * email
Email in the list.
Definition: email.h:132
The envelope/body of an email.
Definition: email.h:37
int msgno
Number displayed to the user.
Definition: email.h:110
struct AddressList sender
Email's sender.
Definition: envelope.h:63
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
#define mutt_buffer_mktemp(buf)
Definition: tmp.h:37
+ 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 940 of file crypt.c.

941{
942 if (!WithCrypto)
943 return 0;
944
945 struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
946 const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
947 const char *self_encrypt = NULL;
948
949 /* Do a quick check to make sure that we can find all of the encryption
950 * keys if the user has requested this service. */
951
952 *keylist = NULL;
953
954#ifdef USE_AUTOCRYPT
955 if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
956 {
958 return -1;
959 return 0;
960 }
961#endif
962
964 OptPgpCheckTrust = true;
965
966 mutt_addrlist_copy(&addrlist, &e->env->to, false);
967 mutt_addrlist_copy(&addrlist, &e->env->cc, false);
968 mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
969 mutt_addrlist_qualify(&addrlist, fqdn);
970 mutt_addrlist_dedupe(&addrlist);
971
972 if (oppenc_mode || (e->security & SEC_ENCRYPT))
973 {
974 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
975 {
976 *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
977 if (!*keylist)
978 {
979 mutt_addrlist_clear(&addrlist);
980 return -1;
981 }
982 OptPgpCheckTrust = false;
983 const bool c_pgp_self_encrypt = cs_subset_bool(NeoMutt->sub, "pgp_self_encrypt");
984 const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
985 const enum QuadOption c_pgp_encrypt_self = cs_subset_quad(NeoMutt->sub, "pgp_encrypt_self");
986 if (c_pgp_self_encrypt || (c_pgp_encrypt_self == MUTT_YES))
987 self_encrypt = c_pgp_default_key;
988 }
990 {
991 *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
992 if (!*keylist)
993 {
994 mutt_addrlist_clear(&addrlist);
995 return -1;
996 }
997 const bool c_smime_self_encrypt = cs_subset_bool(NeoMutt->sub, "smime_self_encrypt");
998 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
999 const enum QuadOption c_smime_encrypt_self = cs_subset_quad(NeoMutt->sub, "smime_encrypt_self");
1000 if (c_smime_self_encrypt || (c_smime_encrypt_self == MUTT_YES))
1001 self_encrypt = c_smime_default_key;
1002 }
1003 }
1004
1005 if (!oppenc_mode && self_encrypt)
1006 {
1007 const size_t keylist_size = mutt_str_len(*keylist);
1008 mutt_mem_realloc(keylist, keylist_size + mutt_str_len(self_encrypt) + 2);
1009 sprintf(*keylist + keylist_size, " %s", self_encrypt);
1010 }
1011
1012 mutt_addrlist_clear(&addrlist);
1013
1014 return 0;
1015}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:745
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:656
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1443
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1380
@ 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:569
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * crypt_smime_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:475
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:316
bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: globals.c:82
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#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:700
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 1024 of file crypt.c.

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

◆ crypt_fetch_signatures()

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

Create an array of an emails parts.

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

Definition at line 1053 of file crypt.c.

1054{
1055 if (!WithCrypto)
1056 return;
1057
1058 for (; a; a = a->next)
1059 {
1060 if (a->type == TYPE_MULTIPART)
1061 {
1062 crypt_fetch_signatures(signatures, a->parts, n);
1063 }
1064 else
1065 {
1066 if ((*n % 5) == 0)
1067 mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1068
1069 (*signatures)[(*n)++] = a;
1070 }
1071 }
1072}
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1053
+ 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 1079 of file crypt.c.

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

◆ crypt_get_fingerprint_or_id()

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

Get the fingerprint or long key ID.

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

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

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

Definition at line 1267 of file crypt.c.

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

1357{
1358 /* or should we require the "0x"? */
1359 if (mutt_strn_equal(s, "0x", 2))
1360 s += 2;
1361 if (strlen(s) % 8)
1362 return false;
1363 while (*s)
1364 if (!strchr("0123456789ABCDEFabcdef", *s++))
1365 return false;
1366
1367 return true;
1368}
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:496
+ Here is the call graph for this function:
+ Here is the caller graph for this function: