NeoMutt  2025-12-11-1009-ga75d9e
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
crypt.c File Reference

Signing/encryption multiplexor. More...

#include "config.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 "cryptglue.h"
#include "globals.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
  • Alejandro Colomar
  • Rayford Shireman

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

65{
66 char p[256] = { 0 };
67 char tmp[512] = { 0 };
68
69 if (!WithCrypto)
70 return;
71
72 const bool c_crypt_timestamp = cs_subset_bool(NeoMutt->sub, "crypt_timestamp");
73 if (c_crypt_timestamp)
74 {
75 mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), mutt_date_now());
76 }
77 else
78 {
79 *p = '\0';
80 }
81
82 snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
83 state_attach_puts(state, tmp);
84}
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:957
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:459
#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:104
#define WithCrypto
Definition lib.h:132
#define NONULL(x)
Definition string2.h:44
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
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 89 of file crypt.c.

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

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

157{
158 struct Body *pbody = NULL;
159 struct Body *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_NONE;
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_str_replace(&protected_headers->message_id, e->env->message_id);
287 mutt_list_copy_tail(&protected_headers->references, &e->env->references);
288 mutt_list_copy_tail(&protected_headers->in_reply_to, &e->env->in_reply_to);
289 mutt_env_to_intl(protected_headers, NULL, NULL);
290 }
291 mutt_prepare_envelope(protected_headers, 0, NeoMutt->sub);
292
294 e->body->mime_headers = protected_headers;
295 mutt_param_set(&e->body->parameter, "protected-headers", "v1");
296 }
297
298#ifdef USE_AUTOCRYPT
299 /* A note about e->body->mime_headers. If postpone or send
300 * fails, the mime_headers is cleared out before returning to the
301 * compose menu. So despite the "robustness" code above and in the
302 * gen_gossip_list function below, mime_headers will not be set when
303 * entering mutt_protect().
304 *
305 * This is important to note because the user could toggle
306 * $crypt_protected_headers_write or $autocrypt off back in the
307 * compose menu. We don't want mutt_rfc822_write_header() to write
308 * stale data from one option if the other is set.
309 */
310 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
311 if (c_autocrypt && !postpone && (security & SEC_AUTOCRYPT))
312 {
314 }
315#endif
316
317 if (sign)
318 {
319 if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
320 {
321 tmp_pbody = crypt_smime_sign_message(e->body, &e->env->from);
322 if (!tmp_pbody)
323 goto bail;
324 pbody = tmp_pbody;
325 tmp_smime_pbody = tmp_pbody;
326 }
327
328 const bool c_pgp_retainable_sigs = cs_subset_bool(NeoMutt->sub, "pgp_retainable_sigs");
329 if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
330 (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || c_pgp_retainable_sigs))
331 {
332 tmp_pbody = crypt_pgp_sign_message(e->body, &e->env->from);
333 if (!tmp_pbody)
334 goto bail;
335
336 has_retainable_sig = true;
337 sign = SEC_NONE;
338 pbody = tmp_pbody;
339 tmp_pgp_pbody = tmp_pbody;
340 }
341 }
342
343 if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
344 {
345 if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
346 {
347 tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
348 if (!tmp_pbody)
349 {
350 /* signed ? free it! */
351 goto bail;
352 }
353 /* free tmp_body if messages was signed AND encrypted ... */
354 if ((tmp_smime_pbody != e->body) && (tmp_smime_pbody != tmp_pbody))
355 {
356 /* detach and don't delete e->body,
357 * which tmp_smime_pbody->parts after signing. */
358 tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
359 e->body->next = NULL;
360 mutt_body_free(&tmp_smime_pbody);
361 }
362 pbody = tmp_pbody;
363 }
364
365 if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
366 {
367 pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
368 if (!pbody)
369 {
370 /* did we perform a retainable signature? */
371 if (has_retainable_sig)
372 {
373 /* remove the outer multipart layer */
374 tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
375 /* get rid of the signature */
376 mutt_body_free(&tmp_pgp_pbody->next);
377 }
378
379 goto bail;
380 }
381
382 // destroy temporary signature envelope when doing retainable signatures.
383 if (has_retainable_sig)
384 {
385 tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
386 mutt_body_free(&tmp_pgp_pbody->next);
387 }
388 }
389 }
390
391 if (pbody)
392 {
393 e->body = pbody;
394 return 0;
395 }
396
397bail:
399 mutt_param_delete(&e->body->parameter, "protected-headers");
400 return -1;
401}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:776
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition address.c:463
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition autocrypt.c:844
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:131
struct Body * crypt_smime_build_smime_entity(struct Body *b, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity().
Definition cryptglue.c:592
struct Body * crypt_smime_sign_message(struct Body *b, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message().
Definition cryptglue.c:578
struct Body * crypt_pgp_traditional_encryptsign(struct Body *b, SecurityFlags flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign().
Definition cryptglue.c:335
struct Body * crypt_pgp_sign_message(struct Body *b, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message().
Definition cryptglue.c:377
void crypt_pgp_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender().
Definition cryptglue.c:472
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender().
Definition cryptglue.c:646
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:391
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:152
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:350
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition envelope.c:68
#define mutt_error(...)
Definition logging2.h:94
void mutt_list_copy_tail(struct ListHead *dst, const struct ListHead *src)
Copy a list into another list.
Definition list.c:278
@ 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:133
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:678
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
uint16_t SecurityFlags
Definition lib.h:104
@ SEC_NONE
No flags are set.
Definition lib.h:91
@ SEC_SIGN
Email is signed.
Definition lib.h:93
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
@ SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition lib.h:101
#define PGP_INLINE
Email is inline PGP encrypted/signed.
Definition lib.h:116
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:384
#define TAILQ_FIRST(head)
Definition queue.h:780
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default 'from' Address.
Definition send.c:1405
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition sendlib.c:750
An email address.
Definition address.h:35
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
struct Envelope * mime_headers
Memory hole protected headers.
Definition body.h:76
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
struct Body * next
next attachment in the list
Definition body.h:72
char * subtype
content-type subtype
Definition body.h:61
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
char * message_id
Message ID.
Definition envelope.h:73
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_NONE)

Definition at line 409 of file crypt.c.

410{
411 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "signed"))
412 {
413 return SEC_NONE;
414 }
415
416 char *p = mutt_param_get(&b->parameter, "protocol");
417 if (!p)
418 return SEC_NONE;
419
420 if (mutt_istr_equal(p, "multipart/mixed"))
421 return SEC_SIGN;
422
423 if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_istr_equal(p, "application/pgp-signature"))
424 {
425 return PGP_SIGN;
426 }
427
428 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
429 (mutt_istr_equal(p, "application/x-pkcs7-signature") ||
430 mutt_istr_equal(p, "application/pkcs7-signature")))
431 {
432 return SMIME_SIGN;
433 }
434
435 return SEC_NONE;
436}
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
#define PGP_SIGN
Email is PGP signed.
Definition lib.h:113
#define SMIME_SIGN
Email is S/MIME signed.
Definition lib.h:119
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_NONE)

Definition at line 444 of file crypt.c.

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

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

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

506{
508 return SEC_NONE;
509
510 if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
511 {
512 return SEC_NONE;
513 }
514
515 b = b->parts;
516 if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
517 !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
518 {
519 return SEC_NONE;
520 }
521
522 b = b->next;
523 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
524 !mutt_istr_equal(b->subtype, "pgp-encrypted"))
525 {
526 return SEC_NONE;
527 }
528
529 b = b->next;
530 if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
531 !mutt_istr_equal(b->subtype, "octet-stream"))
532 {
533 return SEC_NONE;
534 }
535
536 b = b->next;
537 if (b)
538 return SEC_NONE;
539
540 return PGP_ENCRYPT;
541}
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_NONE)

Definition at line 549 of file crypt.c.

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

Definition at line 610 of file crypt.c.

611{
612 if (!b)
613 return SEC_NONE;
614
615 if (((b->type & TYPE_APPLICATION) == 0) || !b->subtype)
616 return SEC_NONE;
617
618 char *t = NULL;
619 bool complain = false;
620 /* S/MIME MIME types don't need x- anymore, see RFC2311 */
621 if (mutt_istr_equal(b->subtype, "x-pkcs7-mime") || mutt_istr_equal(b->subtype, "pkcs7-mime"))
622 {
623 t = mutt_param_get(&b->parameter, "smime-type");
624 if (t)
625 {
626 if (mutt_istr_equal(t, "enveloped-data"))
627 return SMIME_ENCRYPT;
628 if (mutt_istr_equal(t, "signed-data"))
629 return SMIME_SIGN | SMIME_OPAQUE;
630 return SEC_NONE;
631 }
632 /* Netscape 4.7 uses
633 * Content-Description: S/MIME Encrypted Message
634 * instead of Content-Type parameter */
635 if (mutt_istr_equal(b->description, "S/MIME Encrypted Message"))
636 return SMIME_ENCRYPT;
637 complain = true;
638 }
639 else if (!mutt_istr_equal(b->subtype, "octet-stream"))
640 {
641 return SEC_NONE;
642 }
643
644 t = mutt_param_get(&b->parameter, "name");
645
646 if (!t)
647 t = b->d_filename;
648 if (!t)
649 t = b->filename;
650 if (!t)
651 {
652 if (complain)
653 {
654 mutt_message(_("S/MIME messages with no hints on content are unsupported"));
655 }
656 return SEC_NONE;
657 }
658
659 /* no .p7c, .p10 support yet. */
660
661 int len = mutt_str_len(t) - 4;
662 if ((len > 0) && (*(t + len) == '.'))
663 {
664 len++;
665 if (mutt_istr_equal((t + len), "p7m"))
666 {
667 const char *const c_smime_pkcs7_default_smime_type =
668 cs_subset_string(NeoMutt->sub, "smime_pkcs7_default_smime_type");
669 if (mutt_istr_equal(c_smime_pkcs7_default_smime_type, "signed"))
670 return SMIME_SIGN | SMIME_OPAQUE;
671 else if (mutt_istr_equal(c_smime_pkcs7_default_smime_type, "enveloped"))
672 return SMIME_ENCRYPT;
673 else
674 return SEC_NONE;
675 }
676 else if (mutt_istr_equal((t + len), "p7s"))
677 {
678 return SMIME_SIGN | SMIME_OPAQUE;
679 }
680 }
681
682 return SEC_NONE;
683}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
#define SMIME_OPAQUE
Email has an opaque S/MIME signature.
Definition lib.h:122
#define SMIME_ENCRYPT
Email is S/MIME encrypted.
Definition lib.h:118
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:59
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_NONE)

Set the cached status values if there are any.

Definition at line 693 of file crypt.c.

694{
695 if (!WithCrypto || !b)
696 return SEC_NONE;
697
699
700 if (b->type == TYPE_APPLICATION)
701 {
704
706 {
708 if (rc && b->goodsig)
709 rc |= SEC_GOODSIGN;
710 if (rc && b->badsig)
711 rc |= SEC_BADSIGN;
712 }
713 }
714 else if (((WithCrypto & APPLICATION_PGP) != 0) && (b->type == TYPE_TEXT))
715 {
717 if (rc && b->goodsig)
718 rc |= SEC_GOODSIGN;
719 }
720
721 if (b->type == TYPE_MULTIPART)
722 {
726
727 if (rc && b->goodsig)
728 rc |= SEC_GOODSIGN;
729#ifdef USE_AUTOCRYPT
730 if (rc && b->is_autocrypt)
731 rc |= SEC_AUTOCRYPT;
732#endif
733 }
734
735 if ((b->type == TYPE_MULTIPART) || (b->type == TYPE_MESSAGE))
736 {
737 SecurityFlags u = b->parts ? SEC_ALL_FLAGS : SEC_NONE; /* Bits set in all parts */
738 SecurityFlags w = SEC_NONE; /* Bits set in any part */
739
740 for (b = b->parts; b; b = b->next)
741 {
742 const SecurityFlags v = crypt_query(b);
743 u &= v;
744 w |= v;
745 }
746 rc |= u | (w & ~SEC_GOODSIGN);
747
748 if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
749 rc |= SEC_PARTSIGN;
750 }
751
752 return rc;
753}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition crypt.c:409
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:610
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition crypt.c:505
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition crypt.c:549
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:693
@ TYPE_MESSAGE
Type: 'message/*'.
Definition mime.h:35
@ SEC_BADSIGN
Email has a bad signature.
Definition lib.h:95
@ SEC_PARTSIGN
Not all parts of the email is signed.
Definition lib.h:96
@ SEC_GOODSIGN
Email has a valid signature.
Definition lib.h:94
#define SEC_ALL_FLAGS
Mask for all security flags.
Definition lib.h:110
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 765 of file crypt.c.

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

816{
817 if (!WithCrypto)
818 return;
819
820 const bool c_pgp_strict_enc = cs_subset_bool(NeoMutt->sub, "pgp_strict_enc");
821 while (b)
822 {
823 if (b->type == TYPE_MULTIPART)
824 {
825 if (b->encoding != ENC_7BIT)
826 {
827 b->encoding = ENC_7BIT;
829 }
830 else if (((WithCrypto & APPLICATION_PGP) != 0) && c_pgp_strict_enc)
831 {
833 }
834 }
835 else if ((b->type == TYPE_MESSAGE) && !mutt_istr_equal(b->subtype, "delivery-status"))
836 {
837 if (b->encoding != ENC_7BIT)
839 }
840 else if (b->encoding == ENC_8BIT)
841 {
843 }
844 else if (b->encoding == ENC_BINARY)
845 {
846 b->encoding = ENC_BASE64;
847 }
848 else if (b->content && (b->encoding != ENC_BASE64) &&
849 (b->content->from || (b->content->space && c_pgp_strict_enc)))
850 {
852 }
853 b = b->next;
854 }
855}
void crypt_convert_to_7bit(struct Body *b)
Convert an email to 7bit encoding.
Definition crypt.c:815
@ 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:261
struct Content * content
Detailed info about the content of the attachment.
Definition body.h:70
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition body.h:41
bool space
Whitespace at the end of lines?
Definition content.h:42
bool from
Has a line beginning with "From "?
Definition content.h:44
Here is the call graph for this function:
Here is the caller graph for this function:

◆ crypt_extract_keys_from_messages()

void crypt_extract_keys_from_messages ( struct Mailbox * m,
struct EmailArray * ea )

Extract keys from a message.

Parameters
mMailbox
eaArray of Emails to process

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

Definition at line 864 of file crypt.c.

865{
866 if (!WithCrypto)
867 return;
868
869 struct Buffer *tempfile = buf_pool_get();
870 buf_mktemp(tempfile);
871 FILE *fp_out = mutt_file_fopen(buf_string(tempfile), "w");
872 if (!fp_out)
873 {
874 mutt_perror("%s", buf_string(tempfile));
875 goto cleanup;
876 }
877
880
881 struct Email **ep = NULL;
882 ARRAY_FOREACH(ep, ea)
883 {
884 struct Email *e = *ep;
885 struct Message *msg = mx_msg_open(m, e);
886 if (!msg)
887 {
888 continue;
889 }
892 {
893 mx_msg_close(m, &msg);
894 mutt_file_fclose(&fp_out);
895 break;
896 }
897
898 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
899 {
901 fflush(fp_out);
902
903 mutt_endwin();
904 puts(_("Trying to extract PGP keys...\n"));
906 }
907
909 {
910 const bool encrypt = e->security & SEC_ENCRYPT;
911 mutt_copy_message(fp_out, e, msg,
914 CH_NONE, 0);
915 fflush(fp_out);
916
917 const char *mbox = NULL;
918 if (!TAILQ_EMPTY(&e->env->from))
919 {
921 mbox = buf_string(TAILQ_FIRST(&e->env->from)->mailbox);
922 }
923 else if (!TAILQ_EMPTY(&e->env->sender))
924 {
926 mbox = buf_string(TAILQ_FIRST(&e->env->sender)->mailbox);
927 }
928 if (mbox)
929 {
930 mutt_endwin();
931 puts(_("Trying to extract S/MIME certificates..."));
932 crypt_smime_invoke_import(buf_string(tempfile), mbox);
933 }
934 }
935 mx_msg_close(m, &msg);
936
937 rewind(fp_out);
938 }
939
940 mutt_file_fclose(&fp_out);
941 if (isendwin())
943
944 mutt_file_unlink(buf_string(tempfile));
945
947 OptDontHandlePgpKeys = false;
948
949cleanup:
950 buf_pool_release(&tempfile);
951}
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition alias.c:297
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:628
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_email.c:920
@ MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition copy_email.h:52
@ MUTT_CM_DECODE
Decode the message body into text/plain.
Definition copy_email.h:44
@ MUTT_CM_NOHEADER
Don't copy the message header.
Definition copy_email.h:42
@ MUTT_CM_CHARCONV
Perform character set conversions.
Definition copy_email.h:48
@ MUTT_CM_NONE
No flags are set.
Definition copy_email.h:41
#define MUTT_CM_DECODE_CRYPT
Combination flag for decoding any kind of cryptography (PGP or S/MIME).
Definition copy_email.h:58
@ CH_NONE
No flags are set.
Definition copy_email.h:65
void crypt_pgp_invoke_import(const char *fname)
Wrapper for CryptModuleSpecs::pgp_invoke_import().
Definition cryptglue.c:420
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import().
Definition cryptglue.c:606
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:174
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition globals.c:46
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1185
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1139
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define TAILQ_EMPTY(head)
Definition queue.h:778
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 967 of file crypt.c.

968{
969 if (!WithCrypto)
970 return 0;
971
972 struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
973 const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
974 const char *self_encrypt = NULL;
975
976 /* Do a quick check to make sure that we can find all of the encryption
977 * keys if the user has requested this service. */
978
979 *keylist = NULL;
980
981#ifdef USE_AUTOCRYPT
982 if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
983 {
985 return -1;
986 return 0;
987 }
988#endif
989
991 OptPgpCheckTrust = true;
992
993 mutt_addrlist_copy(&addrlist, &e->env->to, false);
994 mutt_addrlist_copy(&addrlist, &e->env->cc, false);
995 mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
996 mutt_addrlist_qualify(&addrlist, fqdn);
997 mutt_addrlist_dedupe(&addrlist);
998
999 if (oppenc_mode || (e->security & SEC_ENCRYPT))
1000 {
1001 if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
1002 {
1003 *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
1004 if (!*keylist)
1005 {
1006 mutt_addrlist_clear(&addrlist);
1007 return -1;
1008 }
1009 OptPgpCheckTrust = false;
1010 const bool c_pgp_self_encrypt = cs_subset_bool(NeoMutt->sub, "pgp_self_encrypt");
1011 const char *const c_pgp_default_key = cs_subset_string(NeoMutt->sub, "pgp_default_key");
1012 const enum QuadOption c_pgp_encrypt_self = cs_subset_quad(NeoMutt->sub, "pgp_encrypt_self");
1013 if (c_pgp_self_encrypt || (c_pgp_encrypt_self == MUTT_YES))
1014 self_encrypt = c_pgp_default_key;
1015 }
1016 if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
1017 {
1018 *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
1019 if (!*keylist)
1020 {
1021 mutt_addrlist_clear(&addrlist);
1022 return -1;
1023 }
1024 const bool c_smime_self_encrypt = cs_subset_bool(NeoMutt->sub, "smime_self_encrypt");
1025 const char *const c_smime_default_key = cs_subset_string(NeoMutt->sub, "smime_default_key");
1026 const enum QuadOption c_smime_encrypt_self = cs_subset_quad(NeoMutt->sub, "smime_encrypt_self");
1027 if (c_smime_self_encrypt || (c_smime_encrypt_self == MUTT_YES))
1028 self_encrypt = c_smime_default_key;
1029 }
1030 }
1031
1032 if (!oppenc_mode && self_encrypt)
1033 {
1034 const size_t keylist_size = mutt_str_len(*keylist);
1035 MUTT_MEM_REALLOC(keylist, keylist_size + mutt_str_len(self_encrypt) + 2, char);
1036 sprintf(*keylist + keylist_size, " %s", self_encrypt);
1037 }
1038
1039 mutt_addrlist_clear(&addrlist);
1040
1041 return 0;
1042}
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition address.c:687
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1475
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition address.c:1410
@ AUTOCRYPT_REC_NO
Do no use Autocrypt.
Definition lib.h:168
enum AutocryptRec mutt_autocrypt_ui_recommendation(const struct Email *e, char **keylist)
Get the recommended action for an Email.
Definition autocrypt.c:578
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:564
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys().
Definition cryptglue.c:363
bool OptPgpCheckTrust
(pseudo) used by dlg_pgp()
Definition globals.c:55
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:55
QuadOption
Possible values for a quad-option.
Definition quad.h:36
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition sendlib.c:717
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 1051 of file crypt.c.

1052{
1053 if (!WithCrypto)
1054 return;
1055
1056 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
1057 if (!(c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT)))
1058 return;
1059
1060 char *pgpkeylist = NULL;
1061
1062 crypt_get_keys(e, &pgpkeylist, true);
1063 if (pgpkeylist)
1064 {
1065 e->security |= SEC_ENCRYPT;
1066 FREE(&pgpkeylist);
1067 }
1068 else
1069 {
1070 e->security &= ~SEC_ENCRYPT;
1071 }
1072}
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition crypt.c:967
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
@ SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition lib.h:100
Here is the call graph for this function:
Here is the caller graph for this function:

◆ crypt_fetch_signatures()

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

1081{
1082 if (!WithCrypto)
1083 return;
1084
1085 for (; b; b = b->next)
1086 {
1087 if (b->type == TYPE_MULTIPART)
1088 {
1089 crypt_fetch_signatures(b_sigs, b->parts, n);
1090 }
1091 else
1092 {
1093 if ((*n % 5) == 0)
1094 MUTT_MEM_REALLOC(b_sigs, *n + 6, struct Body *);
1095
1096 (*b_sigs)[(*n)++] = b;
1097 }
1098 }
1099}
static void crypt_fetch_signatures(struct Body ***b_sigs, struct Body *b, int *n)
Create an array of an emails parts.
Definition crypt.c:1080
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 1106 of file crypt.c.

1107{
1108 const bool c_crypt_protected_headers_write = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_write");
1109 const char *const c_crypt_protected_headers_subject =
1110 cs_subset_string(NeoMutt->sub, "crypt_protected_headers_subject");
1111 if (c_crypt_protected_headers_write && (e->security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) &&
1112 !(e->security & SEC_INLINE) && c_crypt_protected_headers_subject)
1113 {
1114 return true;
1115 }
1116
1117 return false;
1118}
@ SEC_INLINE
Email has an inline signature.
Definition lib.h:99
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 1396 of file crypt.c.

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

1490{
1491 /* or should we require the "0x"? */
1492 if (mutt_strn_equal(s, "0x", 2))
1493 s += 2;
1494 if (strlen(s) % 8)
1495 return false;
1496 while (*s)
1497 if (!strchr("0123456789ABCDEFabcdef", *s++))
1498 return false;
1499
1500 return true;
1501}
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:429
Here is the call graph for this function:
Here is the caller graph for this function: