NeoMutt  2024-04-25-76-g20fe7b
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 (const 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 *b, struct State *state, const char *tempfile)
 Write the message body/part.
 
void crypt_convert_to_7bit (struct Body *b)
 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 ***b_sigs, struct Body *b, 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_email, struct State *state)
 Handler for protected headers - Implements handler_t -.
 
int mutt_signed_handler (struct Body *b_email, struct State *state)
 Handler for "multipart/signed" - 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
  • Richard Russon
  • Pietro Cerutti
  • Anna Figueiredo Gomes

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 65 of file crypt.c.

66{
67 char p[256] = { 0 };
68 char tmp[512] = { 0 };
69
70 if (!WithCrypto)
71 return;
72
73 const bool c_crypt_timestamp = cs_subset_bool(NeoMutt->sub, "crypt_timestamp");
74 if (c_crypt_timestamp)
75 {
76 mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), mutt_date_now());
77 }
78 else
79 {
80 *p = '\0';
81 }
82
83 snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
84 state_attach_puts(state, tmp);
85}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:951
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:456
#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:103
#define WithCrypto
Definition: lib.h:116
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
+ 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 90 of file crypt.c.

91{
94
97
98 if (WithCrypto)
99 {
100 /* L10N: Due to the implementation details (e.g. some passwords are managed
101 by gpg-agent) we can't know whether we forgot zero, 1, 12, ...
102 passwords. So in English we use "Passphrases". Your language might
103 have other means to express this. */
104 mutt_message(_("Passphrases forgotten"));
105 }
106}
void crypt_smime_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:412
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:190
#define mutt_message(...)
Definition: logging2.h:91
#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 132 of file crypt.c.

133{
134 bool rc = false;
135
136#ifndef DEBUG
137 disable_coredumps();
138#endif
139
140 if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & APPLICATION_PGP))
142
143 if (((WithCrypto & APPLICATION_SMIME) != 0) && (flags & APPLICATION_SMIME))
145
146 return rc;
147}
bool crypt_smime_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:421
bool crypt_pgp_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:199
+ 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 157 of file crypt.c.

158{
159 struct Body *pbody = NULL, *tmp_pbody = NULL;
160 struct Body *tmp_smime_pbody = NULL;
161 struct Body *tmp_pgp_pbody = NULL;
162 bool has_retainable_sig = false;
163
164 if (!WithCrypto)
165 return -1;
166
167 SecurityFlags security = e->security;
168 int sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
169 if (postpone)
170 {
171 sign = SEC_NO_FLAGS;
172 security &= ~SEC_SIGN;
173 }
174
175 if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
176 return 0;
177
178 if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
179 return -1;
180
181 if (((WithCrypto & APPLICATION_PGP) != 0) && !(security & SEC_AUTOCRYPT) &&
182 ((security & PGP_INLINE) == PGP_INLINE))
183 {
184 if ((e->body->type != TYPE_TEXT) || !mutt_istr_equal(e->body->subtype, "plain"))
185 {
186 if (query_quadoption(_("Inline PGP can't be used with attachments. Revert to PGP/MIME?"),
187 NeoMutt->sub, "pgp_mime_auto") != MUTT_YES)
188 {
189 mutt_error(_("Mail not sent: inline PGP can't be used with attachments"));
190 return -1;
191 }
192 }
193 else if (mutt_istr_equal("flowed", mutt_param_get(&e->body->parameter, "format")))
194 {
195 if ((query_quadoption(_("Inline PGP can't be used with format=flowed. Revert to PGP/MIME?"),
196 NeoMutt->sub, "pgp_mime_auto")) != MUTT_YES)
197 {
198 mutt_error(_("Mail not sent: inline PGP can't be used with format=flowed"));
199 return -1;
200 }
201 }
202 else
203 {
204 /* they really want to send it inline... go for it */
205 if (!isendwin())
206 {
207 mutt_endwin();
208 puts(_("Invoking PGP..."));
209 }
210 pbody = crypt_pgp_traditional_encryptsign(e->body, security, keylist);
211 if (pbody)
212 {
213 e->body = pbody;
214 return 0;
215 }
216
217 /* otherwise inline won't work...ask for revert */
218 if (query_quadoption(_("Message can't be sent inline. Revert to using PGP/MIME?"),
219 NeoMutt->sub, "pgp_mime_auto") != MUTT_YES)
220 {
221 mutt_error(_("Mail not sent"));
222 return -1;
223 }
224 }
225
226 /* go ahead with PGP/MIME */
227 }
228
229 if (!isendwin())
230 mutt_endwin();
231
233 tmp_smime_pbody = e->body;
235 tmp_pgp_pbody = e->body;
236
237#ifdef CRYPT_BACKEND_GPGME
238 const bool c_crypt_use_pka = cs_subset_bool(NeoMutt->sub, "crypt_use_pka");
239 if (sign && c_crypt_use_pka)
240#else
241 if (sign)
242#endif
243 {
244 /* Set sender (necessary for e.g. PKA). */
245 const char *mailbox = NULL;
246 struct Address *from = TAILQ_FIRST(&e->env->from);
247 bool free_from = false;
248
249 if (!from)
250 {
251 free_from = true;
253 }
254
255 mailbox = buf_string(from->mailbox);
256 const struct Address *c_envelope_from_address = cs_subset_address(NeoMutt->sub, "envelope_from_address");
257 if (!mailbox && c_envelope_from_address)
258 mailbox = buf_string(c_envelope_from_address->mailbox);
259
260 if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
262 else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
264
265 if (free_from)
266 mutt_addr_free(&from);
267 }
268
269 const bool c_crypt_protected_headers_write = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_write");
270 if (c_crypt_protected_headers_write)
271 {
272 const bool c_devel_security = cs_subset_bool(NeoMutt->sub, "devel_security");
273 struct Envelope *protected_headers = mutt_env_new();
274 mutt_env_set_subject(protected_headers, e->env->subject);
275 if (c_devel_security)
276 {
277 mutt_addrlist_copy(&protected_headers->return_path, &e->env->return_path, false);
278 mutt_addrlist_copy(&protected_headers->from, &e->env->from, false);
279 mutt_addrlist_copy(&protected_headers->to, &e->env->to, false);
280 mutt_addrlist_copy(&protected_headers->cc, &e->env->cc, false);
281 mutt_addrlist_copy(&protected_headers->sender, &e->env->sender, false);
282 mutt_addrlist_copy(&protected_headers->reply_to, &e->env->reply_to, false);
283 mutt_addrlist_copy(&protected_headers->mail_followup_to,
284 &e->env->mail_followup_to, false);
285 mutt_addrlist_copy(&protected_headers->x_original_to, &e->env->x_original_to, false);
286 mutt_list_copy_tail(&protected_headers->references, &e->env->references);
287 mutt_list_copy_tail(&protected_headers->in_reply_to, &e->env->in_reply_to);
288 mutt_env_to_intl(protected_headers, NULL, NULL);
289 }
290 mutt_prepare_envelope(protected_headers, 0, NeoMutt->sub);
291
293 e->body->mime_headers = protected_headers;
294 mutt_param_set(&e->body->parameter, "protected-headers", "v1");
295 }
296
297#ifdef USE_AUTOCRYPT
298 /* A note about e->body->mime_headers. If postpone or send
299 * fails, the mime_headers is cleared out before returning to the
300 * compose menu. So despite the "robustness" code above and in the
301 * gen_gossip_list function below, mime_headers will not be set when
302 * entering mutt_protect().
303 *
304 * This is important to note because the user could toggle
305 * $crypt_protected_headers_write or $autocrypt off back in the
306 * compose menu. We don't want mutt_rfc822_write_header() to write
307 * stale data from one option if the other is set.
308 */
309 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
310 if (c_autocrypt && !postpone && (security & SEC_AUTOCRYPT))
311 {
313 }
314#endif
315
316 if (sign)
317 {
318 if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
319 {
320 tmp_pbody = crypt_smime_sign_message(e->body, &e->env->from);
321 if (!tmp_pbody)
322 goto bail;
323 pbody = tmp_pbody;
324 tmp_smime_pbody = tmp_pbody;
325 }
326
327 const bool c_pgp_retainable_sigs = cs_subset_bool(NeoMutt->sub, "pgp_retainable_sigs");
328 if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
329 (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || c_pgp_retainable_sigs))
330 {
331 tmp_pbody = crypt_pgp_sign_message(e->body, &e->env->from);
332 if (!tmp_pbody)
333 goto bail;
334
335 has_retainable_sig = true;
336 sign = SEC_NO_FLAGS;
337 pbody = tmp_pbody;
338 tmp_pgp_pbody = tmp_pbody;
339 }
340 }
341
342 if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
343 {
344 if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
345 {
346 tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
347 if (!tmp_pbody)
348 {
349 /* signed ? free it! */
350 goto bail;
351 }
352 /* free tmp_body if messages was signed AND encrypted ... */
353 if ((tmp_smime_pbody != e->body) && (tmp_smime_pbody != tmp_pbody))
354 {
355 /* detach and don't delete e->body,
356 * which tmp_smime_pbody->parts after signing. */
357 tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
358 e->body->next = NULL;
359 mutt_body_free(&tmp_smime_pbody);
360 }
361 pbody = tmp_pbody;
362 }
363
364 if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
365 {
366 pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
367 if (!pbody)
368 {
369 /* did we perform a retainable signature? */
370 if (has_retainable_sig)
371 {
372 /* remove the outer multipart layer */
373 tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
374 /* get rid of the signature */
375 mutt_body_free(&tmp_pgp_pbody->next);
376 }
377
378 goto bail;
379 }
380
381 // destroy temporary signature envelope when doing retainable signatures.
382 if (has_retainable_sig)
383 {
384 tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
385 mutt_body_free(&tmp_pgp_pbody->next);
386 }
387 }
388 }
389
390 if (pbody)
391 {
392 e->body = pbody;
393 return 0;
394 }
395
396bail:
398 mutt_param_delete(&e->body->parameter, "protected-headers");
399 return -1;
400}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:765
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:462
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: config_type.c:272
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:825
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:132
struct Body * crypt_smime_build_smime_entity(struct Body *b, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:496
struct Body * crypt_smime_sign_message(struct Body *b, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:485
struct Body * crypt_pgp_traditional_encryptsign(struct Body *b, SecurityFlags flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:293
struct Body * crypt_pgp_sign_message(struct Body *b, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:326
void crypt_pgp_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:403
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:538
struct Body * crypt_pgp_encrypt_message(struct Email *e, struct Body *b, char *keylist, int sign, const struct AddressList *from)
Wrapper for CryptModuleSpecs::pgp_encrypt_message()
Definition: cryptglue.c:337
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:58
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope's Address fields to Punycode format.
Definition: envelope.c:355
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:126
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition: envelope.c:69
#define mutt_error(...)
Definition: logging2.h:92
void mutt_list_copy_tail(struct ListHead *dst, const struct ListHead *src)
Copy a list into another list.
Definition: list.c:275
@ 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:672
#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:85
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:143
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:111
@ 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:365
#define TAILQ_FIRST(head)
Definition: queue.h:723
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition: send.c:1461
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:780
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:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:43
struct Body * body
List of MIME parts.
Definition: email.h:69
The header of an Email.
Definition: envelope.h:57
struct AddressList return_path
Return path for the Email.
Definition: envelope.h:58
char *const subject
Email's subject.
Definition: envelope.h:70
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:64
struct AddressList x_original_to
Email's 'X-Original-to'.
Definition: envelope.h:66
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:65
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:61
struct AddressList sender
Email's sender.
Definition: envelope.h:63
struct ListHead references
message references (in reverse order)
Definition: envelope.h:83
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
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 408 of file crypt.c.

409{
410 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "signed"))
411 {
412 return SEC_NO_FLAGS;
413 }
414
415 char *p = mutt_param_get(&b->parameter, "protocol");
416 if (!p)
417 return SEC_NO_FLAGS;
418
419 if (mutt_istr_equal(p, "multipart/mixed"))
420 return SEC_SIGN;
421
422 if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_istr_equal(p, "application/pgp-signature"))
423 {
424 return PGP_SIGN;
425 }
426
427 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
428 (mutt_istr_equal(p, "application/x-pkcs7-signature") ||
429 mutt_istr_equal(p, "application/pkcs7-signature")))
430 {
431 return SMIME_SIGN;
432 }
433
434 return SEC_NO_FLAGS;
435}
@ 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 443 of file crypt.c.

444{
445 if ((WithCrypto & APPLICATION_PGP) == 0)
446 return SEC_NO_FLAGS;
447
448 char *p = NULL;
449
450 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
451 !mutt_istr_equal(b->subtype, "encrypted") ||
452 !(p = mutt_param_get(&b->parameter, "protocol")) ||
453 !mutt_istr_equal(p, "application/pgp-encrypted"))
454 {
455 return SEC_NO_FLAGS;
456 }
457
458 return PGP_ENCRYPT;
459}
#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 467 of file crypt.c.

468{
470 return 0;
471
472 b = b->parts;
473 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
474 !mutt_istr_equal(b->subtype, "pgp-encrypted"))
475 {
476 return 0;
477 }
478
479 b = b->next;
480 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
481 !mutt_istr_equal(b->subtype, "octet-stream"))
482 {
483 return 0;
484 }
485
486 return PGP_ENCRYPT;
487}
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:443
@ 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 504 of file crypt.c.

505{
507 return SEC_NO_FLAGS;
508
509 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
510 {
511 return SEC_NO_FLAGS;
512 }
513
514 b = b->parts;
515 if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
516 !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
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, "pgp-encrypted"))
524 {
525 return SEC_NO_FLAGS;
526 }
527
528 b = b->next;
529 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
530 !mutt_istr_equal(b->subtype, "octet-stream"))
531 {
532 return SEC_NO_FLAGS;
533 }
534
535 b = b->next;
536 if (b)
537 return SEC_NO_FLAGS;
538
539 return PGP_ENCRYPT;
540}
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 ( const 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 548 of file crypt.c.

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

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

688{
689 if (!WithCrypto || !b)
690 return SEC_NO_FLAGS;
691
693
694 if (b->type == TYPE_APPLICATION)
695 {
698
700 {
702 if (rc && b->goodsig)
703 rc |= SEC_GOODSIGN;
704 if (rc && b->badsig)
705 rc |= SEC_BADSIGN;
706 }
707 }
708 else if (((WithCrypto & APPLICATION_PGP) != 0) && (b->type == TYPE_TEXT))
709 {
711 if (rc && b->goodsig)
712 rc |= SEC_GOODSIGN;
713 }
714
715 if (b->type == TYPE_MULTIPART)
716 {
720
721 if (rc && b->goodsig)
722 rc |= SEC_GOODSIGN;
723#ifdef USE_AUTOCRYPT
724 if (rc && b->is_autocrypt)
725 rc |= SEC_AUTOCRYPT;
726#endif
727 }
728
729 if ((b->type == TYPE_MULTIPART) || (b->type == TYPE_MESSAGE))
730 {
731 SecurityFlags u = b->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
732 SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
733
734 for (b = b->parts; b; b = b->next)
735 {
736 const SecurityFlags v = crypt_query(b);
737 u &= v;
738 w |= v;
739 }
740 rc |= u | (w & ~SEC_GOODSIGN);
741
742 if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
743 rc |= SEC_PARTSIGN;
744 }
745
746 return rc;
747}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:408
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:609
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:504
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition: crypt.c:548
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:687
@ 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 b,
struct State state,
const char *  tempfile 
)

Write the message body/part.

Parameters
bBody 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 759 of file crypt.c.

760{
761 if (!WithCrypto)
762 return -1;
763
764 FILE *fp = mutt_file_fopen(tempfile, "w");
765 if (!fp)
766 {
767 mutt_perror("%s", tempfile);
768 return -1;
769 }
770
771 if (!mutt_file_seek(state->fp_in, b->hdr_offset, SEEK_SET))
772 {
773 mutt_file_fclose(&fp);
774 return -1;
775 }
776 size_t bytes = b->length + b->offset - b->hdr_offset;
777 bool hadcr = false;
778 while (bytes > 0)
779 {
780 const int c = fgetc(state->fp_in);
781 if (c == EOF)
782 break;
783
784 bytes--;
785
786 if (c == '\r')
787 {
788 hadcr = true;
789 }
790 else
791 {
792 if ((c == '\n') && !hadcr)
793 fputc('\r', fp);
794
795 hadcr = false;
796 }
797
798 fputc(c, fp);
799 }
800 mutt_file_fclose(&fp);
801
802 return 0;
803}
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:778
#define mutt_file_fclose(FP)
Definition: file.h:149
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:148
#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:49
+ 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 b)

Convert an email to 7bit encoding.

Parameters
bBody of email to convert

Definition at line 809 of file crypt.c.

810{
811 if (!WithCrypto)
812 return;
813
814 const bool c_pgp_strict_enc = cs_subset_bool(NeoMutt->sub, "pgp_strict_enc");
815 while (b)
816 {
817 if (b->type == TYPE_MULTIPART)
818 {
819 if (b->encoding != ENC_7BIT)
820 {
821 b->encoding = ENC_7BIT;
823 }
824 else if (((WithCrypto & APPLICATION_PGP) != 0) && c_pgp_strict_enc)
825 {
827 }
828 }
829 else if ((b->type == TYPE_MESSAGE) && !mutt_istr_equal(b->subtype, "delivery-status"))
830 {
831 if (b->encoding != ENC_7BIT)
833 }
834 else if (b->encoding == ENC_8BIT)
835 {
837 }
838 else if (b->encoding == ENC_BINARY)
839 {
840 b->encoding = ENC_BASE64;
841 }
842 else if (b->content && (b->encoding != ENC_BASE64) &&
843 (b->content->from || (b->content->space && c_pgp_strict_enc)))
844 {
846 }
847 b = b->next;
848 }
849}
void crypt_convert_to_7bit(struct Body *b)
Convert an email to 7bit encoding.
Definition: crypt.c:809
@ 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 *b, FILE *fp, struct ConfigSubset *sub)
Convert an email's MIME parts to 7-bit.
Definition: sendlib.c:259
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:43
bool from
Has a line beginning with "From "?
Definition: content.h:45
+ 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 858 of file crypt.c.

859{
860 if (!WithCrypto)
861 return;
862
863 struct Buffer *tempfname = buf_pool_get();
864 buf_mktemp(tempfname);
865 FILE *fp_out = mutt_file_fopen(buf_string(tempfname), "w");
866 if (!fp_out)
867 {
868 mutt_perror("%s", buf_string(tempfname));
869 goto cleanup;
870 }
871
874
875 struct Email **ep = NULL;
876 ARRAY_FOREACH(ep, ea)
877 {
878 struct Email *e = *ep;
879 struct Message *msg = mx_msg_open(m, e);
880 if (!msg)
881 {
882 continue;
883 }
886 {
887 mx_msg_close(m, &msg);
888 mutt_file_fclose(&fp_out);
889 break;
890 }
891
892 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
893 {
895 fflush(fp_out);
896
897 mutt_endwin();
898 puts(_("Trying to extract PGP keys...\n"));
900 }
901
903 {
904 const bool encrypt = e->security & SEC_ENCRYPT;
905 mutt_copy_message(fp_out, e, msg,
908 CH_NO_FLAGS, 0);
909 fflush(fp_out);
910
911 const char *mbox = NULL;
912 if (!TAILQ_EMPTY(&e->env->from))
913 {
915 mbox = buf_string(TAILQ_FIRST(&e->env->from)->mailbox);
916 }
917 else if (!TAILQ_EMPTY(&e->env->sender))
918 {
920 mbox = buf_string(TAILQ_FIRST(&e->env->sender)->mailbox);
921 }
922 if (mbox)
923 {
924 mutt_endwin();
925 puts(_("Trying to extract S/MIME certificates..."));
926 crypt_smime_invoke_import(buf_string(tempfname), mbox);
927 }
928 }
929 mx_msg_close(m, &msg);
930
931 rewind(fp_out);
932 }
933
934 mutt_file_fclose(&fp_out);
935 if (isendwin())
937
938 mutt_file_unlink(buf_string(tempfname));
939
941 OptDontHandlePgpKeys = false;
942
943cleanup:
944 buf_pool_release(&tempfname);
945}
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:295
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:597
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:907
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:40
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:44
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:48
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:37
#define MUTT_CM_DECODE_CRYPT
Definition: copy.h:50
#define MUTT_CM_NOHEADER
Don't copy the message header.
Definition: copy.h:38
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:53
void crypt_pgp_invoke_import(const char *fname)
Wrapper for CryptModuleSpecs::pgp_invoke_import()
Definition: cryptglue.c:363
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import()
Definition: cryptglue.c:507
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:173
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:221
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: globals.c:64
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1180
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1134
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:36
The envelope/body of an email.
Definition: email.h:39
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 961 of file crypt.c.

962{
963 if (!WithCrypto)
964 return 0;
965
966 struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
967 const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
968 const char *self_encrypt = NULL;
969
970 /* Do a quick check to make sure that we can find all of the encryption
971 * keys if the user has requested this service. */
972
973 *keylist = NULL;
974
975#ifdef USE_AUTOCRYPT
976 if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
977 {
979 return -1;
980 return 0;
981 }
982#endif
983
985 OptPgpCheckTrust = true;
986
987 mutt_addrlist_copy(&addrlist, &e->env->to, false);
988 mutt_addrlist_copy(&addrlist, &e->env->cc, false);
989 mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
990 mutt_addrlist_qualify(&addrlist, fqdn);
991 mutt_addrlist_dedupe(&addrlist);
992
993 if (oppenc_mode || (e->security & SEC_ENCRYPT))
994 {
995 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
996 {
997 *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
998 if (!*keylist)
999 {
1000 mutt_addrlist_clear(&addrlist);
1001 return -1;
1002 }
1003 OptPgpCheckTrust = false;
1004 const bool c_pgp_self_encrypt = cs_subset_bool(NeoMutt->sub, "pgp_self_encrypt");
1005 const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
1006 const enum QuadOption c_pgp_encrypt_self = cs_subset_quad(NeoMutt->sub, "pgp_encrypt_self");
1007 if (c_pgp_self_encrypt || (c_pgp_encrypt_self == MUTT_YES))
1008 self_encrypt = c_pgp_default_key;
1009 }
1010 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
1011 {
1012 *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
1013 if (!*keylist)
1014 {
1015 mutt_addrlist_clear(&addrlist);
1016 return -1;
1017 }
1018 const bool c_smime_self_encrypt = cs_subset_bool(NeoMutt->sub, "smime_self_encrypt");
1019 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
1020 const enum QuadOption c_smime_encrypt_self = cs_subset_quad(NeoMutt->sub, "smime_encrypt_self");
1021 if (c_smime_self_encrypt || (c_smime_encrypt_self == MUTT_YES))
1022 self_encrypt = c_smime_default_key;
1023 }
1024 }
1025
1026 if (!oppenc_mode && self_encrypt)
1027 {
1028 const size_t keylist_size = mutt_str_len(*keylist);
1029 mutt_mem_realloc(keylist, keylist_size + mutt_str_len(self_encrypt) + 2);
1030 sprintf(*keylist + keylist_size, " %s", self_encrypt);
1031 }
1032
1033 mutt_addrlist_clear(&addrlist);
1034
1035 return 0;
1036}
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:680
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1460
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1397
@ AUTOCRYPT_REC_NO
Do no use Autocrypt.
Definition: lib.h:160
enum AutocryptRec mutt_autocrypt_ui_recommendation(const struct Email *e, char **keylist)
Get the recommended action for an Email.
Definition: autocrypt.c:560
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:192
char * crypt_smime_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:474
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:315
bool OptPgpCheckTrust
(pseudo) used by dlg_pgp()
Definition: globals.c:73
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:115
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:707
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 1045 of file crypt.c.

1046{
1047 if (!WithCrypto)
1048 return;
1049
1050 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
1051 if (!(c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT)))
1052 return;
1053
1054 char *pgpkeylist = NULL;
1055
1056 crypt_get_keys(e, &pgpkeylist, true);
1057 if (pgpkeylist)
1058 {
1059 e->security |= SEC_ENCRYPT;
1060 FREE(&pgpkeylist);
1061 }
1062 else
1063 {
1064 e->security &= ~SEC_ENCRYPT;
1065 }
1066}
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:961
#define FREE(x)
Definition: memory.h:45
#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 ***  b_sigs,
struct Body b,
int *  n 
)
static

Create an array of an emails parts.

Parameters
[out]b_sigsArray of Body parts
[in]bBody part to examine
[out]nCumulative count of parts

Definition at line 1074 of file crypt.c.

1075{
1076 if (!WithCrypto)
1077 return;
1078
1079 for (; b; b = b->next)
1080 {
1081 if (b->type == TYPE_MULTIPART)
1082 {
1083 crypt_fetch_signatures(b_sigs, b->parts, n);
1084 }
1085 else
1086 {
1087 if ((*n % 5) == 0)
1088 mutt_mem_realloc(b_sigs, (*n + 6) * sizeof(struct Body *));
1089
1090 (*b_sigs)[(*n)++] = b;
1091 }
1092 }
1093}
static void crypt_fetch_signatures(struct Body ***b_sigs, struct Body *b, int *n)
Create an array of an emails parts.
Definition: crypt.c:1074
+ 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 1100 of file crypt.c.

1101{
1102 const bool c_crypt_protected_headers_write = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_write");
1103 const char *const c_crypt_protected_headers_subject =
1104 cs_subset_string(NeoMutt->sub, "crypt_protected_headers_subject");
1105 if (c_crypt_protected_headers_write && (e->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) &&
1106 !(e->security & SEC_INLINE) && c_crypt_protected_headers_subject)
1107 {
1108 return true;
1109 }
1110
1111 return false;
1112}
#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 1380 of file crypt.c.

1382{
1383 const char *ps = NULL, *pl = NULL, *phint = NULL;
1384 char *pfcopy = NULL, *s1 = NULL, *s2 = NULL;
1385 char c;
1386 int isid;
1387 size_t hexdigits;
1388
1389 /* User input may be partial name, fingerprint or short or long key ID,
1390 * independent of `$pgp_long_ids`.
1391 * Fingerprint without spaces is 40 hex digits (SHA-1) or 32 hex digits (MD5).
1392 * Strip leading "0x" for key ID detection and prepare pl and ps to indicate
1393 * if an ID was found and to simplify logic in the key loop's inner
1394 * condition of the caller. */
1395
1396 char *pf = mutt_str_skip_whitespace(p);
1397 if (mutt_istr_startswith(pf, "0x"))
1398 pf += 2;
1399
1400 /* Check if a fingerprint is given, must be hex digits only, blanks
1401 * separating groups of 4 hex digits are allowed. Also pre-check for ID. */
1402 isid = 2; /* unknown */
1403 hexdigits = 0;
1404 s1 = pf;
1405 do
1406 {
1407 c = *(s1++);
1408 if ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) ||
1409 (('a' <= c) && (c <= 'f')))
1410 {
1411 hexdigits++;
1412 if (isid == 2)
1413 isid = 1; /* it is an ID so far */
1414 }
1415 else if (c)
1416 {
1417 isid = 0; /* not an ID */
1418 if ((c == ' ') && ((hexdigits % 4) == 0))
1419 ; /* skip blank before or after 4 hex digits */
1420 else
1421 break; /* any other character or position */
1422 }
1423 } while (c);
1424
1425 /* If at end of input, check for correct fingerprint length and copy if. */
1426 pfcopy = (!c && ((hexdigits == 40) || (hexdigits == 32)) ? mutt_str_dup(pf) : NULL);
1427
1428 if (pfcopy)
1429 {
1430 /* Use pfcopy to strip all spaces from fingerprint and as hint. */
1431 s1 = pfcopy;
1432 s2 = pfcopy;
1433 do
1434 {
1435 *(s1++) = *(s2 = mutt_str_skip_whitespace(s2));
1436 } while (*(s2++));
1437
1438 phint = pfcopy;
1439 ps = NULL;
1440 pl = NULL;
1441 }
1442 else
1443 {
1444 phint = p;
1445 ps = NULL;
1446 pl = NULL;
1447 if (isid == 1)
1448 {
1449 if (mutt_str_len(pf) == 16)
1450 pl = pf; /* long key ID */
1451 else if (mutt_str_len(pf) == 8)
1452 ps = pf; /* short key ID */
1453 }
1454 }
1455
1456 *pphint = phint;
1457 *ppl = pl;
1458 *pps = ps;
1459 return pfcopy;
1460}
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:551
+ 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 1469 of file crypt.c.

1470{
1471 /* or should we require the "0x"? */
1472 if (mutt_strn_equal(s, "0x", 2))
1473 s += 2;
1474 if (strlen(s) % 8)
1475 return false;
1476 while (*s)
1477 if (!strchr("0123456789ABCDEFabcdef", *s++))
1478 return false;
1479
1480 return true;
1481}
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:425
+ Here is the call graph for this function:
+ Here is the caller graph for this function: