NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
gnutls.c File Reference

Handling of GnuTLS encryption. More...

#include "config.h"
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "muttlib.h"
#include "options.h"
#include "ssl.h"
+ Include dependency graph for gnutls.c:

Go to the source code of this file.

Data Structures

struct  TlsSockData
 TLS socket data -. More...
 

Macros

#define CERTERR_VALID   0
 
#define CERTERR_EXPIRED   (1 << 0)
 
#define CERTERR_NOTYETVALID   (1 << 1)
 
#define CERTERR_REVOKED   (1 << 2)
 
#define CERTERR_NOTTRUSTED   (1 << 3)
 
#define CERTERR_HOSTNAME   (1 << 4)
 
#define CERTERR_SIGNERNOTCA   (1 << 5)
 
#define CERTERR_INSECUREALG   (1 << 6)
 
#define CERTERR_OTHER   (1 << 7)
 
#define CERT_SEP   "-----BEGIN"
 

Functions

static int tls_init (void)
 Set up Gnu TLS. More...
 
static int tls_verify_peers (gnutls_session_t tlsstate, gnutls_certificate_status_t *certstat)
 Wrapper for gnutls_certificate_verify_peers() More...
 
static void tls_fingerprint (gnutls_digest_algorithm_t algo, char *buf, size_t buflen, const gnutls_datum_t *data)
 Create a fingerprint of a TLS Certificate. More...
 
static int tls_check_stored_hostname (const gnutls_datum_t *cert, const char *hostname)
 Does the hostname match a stored certificate? More...
 
static int tls_compare_certificates (const gnutls_datum_t *peercert)
 Compare certificates against $certificate_file More...
 
static int tls_check_preauth (const gnutls_datum_t *certdata, gnutls_certificate_status_t certstat, const char *hostname, int chainidx, int *certerr, int *savedcert)
 Prepare a certificate for authentication. More...
 
static void add_cert (const char *title, gnutls_x509_crt_t cert, bool issuer, struct ListHead *list)
 Look up certificate info and save it to a list. More...
 
static int tls_check_one_certificate (const gnutls_datum_t *certdata, gnutls_certificate_status_t certstat, const char *hostname, int idx, size_t len)
 Check a GnuTLS certificate. More...
 
static int tls_check_certificate (struct Connection *conn)
 Check a connection's certificate. More...
 
static void tls_get_client_cert (struct Connection *conn)
 Get the client certificate for a TLS connection. More...
 
static int tls_set_priority (struct TlsSockData *data)
 Set the priority of various protocols. More...
 
static int tls_negotiate (struct Connection *conn)
 Negotiate TLS connection. More...
 
static int tls_socket_poll (struct Connection *conn, time_t wait_secs)
 Check whether a socket read would block - Implements Connection::poll() -. More...
 
static int tls_socket_close (struct Connection *conn)
 Close a TLS socket - Implements Connection::close() -. More...
 
static int tls_socket_open (struct Connection *conn)
 Open a TLS socket - Implements Connection::open() -. More...
 
static int tls_socket_read (struct Connection *conn, char *buf, size_t count)
 Read data from a TLS socket - Implements Connection::read() -. More...
 
static int tls_socket_write (struct Connection *conn, const char *buf, size_t count)
 Write data to a TLS socket - Implements Connection::write() -. More...
 
static int tls_starttls_close (struct Connection *conn)
 Close a TLS connection - Implements Connection::close() -. More...
 
int mutt_ssl_socket_setup (struct Connection *conn)
 Set up SSL socket mulitplexor. More...
 
int mutt_ssl_starttls (struct Connection *conn)
 Negotiate TLS over an already opened connection. More...
 

Variables

const int dialog_row_len = 128
 
static int protocol_priority []
 

Detailed Description

Handling of GnuTLS encryption.

Authors
  • Marco d'Itri
  • Andrew McDonald

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 gnutls.c.

Macro Definition Documentation

◆ CERTERR_VALID

#define CERTERR_VALID   0

Definition at line 48 of file gnutls.c.

◆ CERTERR_EXPIRED

#define CERTERR_EXPIRED   (1 << 0)

Definition at line 49 of file gnutls.c.

◆ CERTERR_NOTYETVALID

#define CERTERR_NOTYETVALID   (1 << 1)

Definition at line 50 of file gnutls.c.

◆ CERTERR_REVOKED

#define CERTERR_REVOKED   (1 << 2)

Definition at line 51 of file gnutls.c.

◆ CERTERR_NOTTRUSTED

#define CERTERR_NOTTRUSTED   (1 << 3)

Definition at line 52 of file gnutls.c.

◆ CERTERR_HOSTNAME

#define CERTERR_HOSTNAME   (1 << 4)

Definition at line 53 of file gnutls.c.

◆ CERTERR_SIGNERNOTCA

#define CERTERR_SIGNERNOTCA   (1 << 5)

Definition at line 54 of file gnutls.c.

◆ CERTERR_INSECUREALG

#define CERTERR_INSECUREALG   (1 << 6)

Definition at line 55 of file gnutls.c.

◆ CERTERR_OTHER

#define CERTERR_OTHER   (1 << 7)

Definition at line 56 of file gnutls.c.

◆ CERT_SEP

#define CERT_SEP   "-----BEGIN"

Definition at line 61 of file gnutls.c.

Function Documentation

◆ tls_init()

static int tls_init ( void  )
static

Set up Gnu TLS.

Return values
0Success
-1Error

Definition at line 90 of file gnutls.c.

91 {
92  static bool init_complete = false;
93  int err;
94 
95  if (init_complete)
96  return 0;
97 
98  err = gnutls_global_init();
99  if (err < 0)
100  {
101  mutt_error("gnutls_global_init: %s", gnutls_strerror(err));
102  return -1;
103  }
104 
105  init_complete = true;
106  return 0;
107 }
#define mutt_error(...)
Definition: logging.h:88
+ Here is the caller graph for this function:

◆ tls_verify_peers()

static int tls_verify_peers ( gnutls_session_t  tlsstate,
gnutls_certificate_status_t *  certstat 
)
static

Wrapper for gnutls_certificate_verify_peers()

Parameters
tlsstateTLS state
certstatCertificate state, e.g. GNUTLS_CERT_INVALID
Return values
0Success If certstat was set. note: this does not mean success
>0Error

Wrapper with sanity-checking.

certstat is technically a bitwise-or of gnutls_certificate_status_t values.

Definition at line 120 of file gnutls.c.

121 {
122  /* gnutls_certificate_verify_peers2() chains to
123  * gnutls_x509_trust_list_verify_crt2(). That function's documentation says:
124  *
125  * When a certificate chain of cert_list_size with more than one
126  * certificates is provided, the verification status will apply to
127  * the first certificate in the chain that failed
128  * verification. The verification process starts from the end of
129  * the chain(from CA to end certificate). The first certificate
130  * in the chain must be the end-certificate while the rest of the
131  * members may be sorted or not.
132  *
133  * This is why tls_check_certificate() loops from CA to host in that order,
134  * calling the menu, and recalling tls_verify_peers() for each approved
135  * cert in the chain.
136  */
137  int rc = gnutls_certificate_verify_peers2(tlsstate, certstat);
138 
139  /* certstat was set */
140  if (rc == 0)
141  return 0;
142 
143  if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND)
144  mutt_error(_("Unable to get certificate from peer"));
145  else
146  mutt_error(_("Certificate verification error (%s)"), gnutls_strerror(rc));
147 
148  return rc;
149 }
#define mutt_error(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
+ Here is the caller graph for this function:

◆ tls_fingerprint()

static void tls_fingerprint ( gnutls_digest_algorithm_t  algo,
char *  buf,
size_t  buflen,
const gnutls_datum_t *  data 
)
static

Create a fingerprint of a TLS Certificate.

Parameters
algoFingerprint algorithm, e.g. GNUTLS_MAC_SHA256
bufBuffer for the fingerprint
buflenLength of the buffer
dataCertificate

Definition at line 158 of file gnutls.c.

160 {
161  unsigned char md[64];
162  size_t n;
163 
164  n = 64;
165 
166  if (gnutls_fingerprint(algo, data, (char *) md, &n) < 0)
167  {
168  snprintf(buf, buflen, _("[unable to calculate]"));
169  }
170  else
171  {
172  for (int i = 0; i < (int) n; i++)
173  {
174  char ch[8];
175  snprintf(ch, 8, "%02X%s", md[i], ((i % 2) ? " " : ""));
176  mutt_str_cat(buf, buflen, ch);
177  }
178  buf[2 * n + n / 2 - 1] = '\0'; /* don't want trailing space */
179  }
180 }
#define _(a)
Definition: message.h:28
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_check_stored_hostname()

static int tls_check_stored_hostname ( const gnutls_datum_t *  cert,
const char *  hostname 
)
static

Does the hostname match a stored certificate?

Parameters
certCertificate
hostnameHostname
Return values
1Hostname match found
0Error, or no match

Definition at line 189 of file gnutls.c.

190 {
191  char *linestr = NULL;
192  size_t linestrsize = 0;
193 
194  /* try checking against names stored in stored certs file */
195  const char *const c_certificate_file =
196  cs_subset_path(NeoMutt->sub, "certificate_file");
197  FILE *fp = mutt_file_fopen(c_certificate_file, "r");
198  if (!fp)
199  return 0;
200 
201  char buf[80];
202  buf[0] = '\0';
203  tls_fingerprint(GNUTLS_DIG_MD5, buf, sizeof(buf), cert);
204  while ((linestr = mutt_file_read_line(linestr, &linestrsize, fp, NULL, MUTT_RL_NO_FLAGS)))
205  {
206  regmatch_t *match = mutt_prex_capture(PREX_GNUTLS_CERT_HOST_HASH, linestr);
207  if (match)
208  {
209  regmatch_t *mhost = &match[PREX_GNUTLS_CERT_HOST_HASH_MATCH_HOST];
210  regmatch_t *mhash = &match[PREX_GNUTLS_CERT_HOST_HASH_MATCH_HASH];
211  linestr[mutt_regmatch_end(mhost)] = '\0';
212  linestr[mutt_regmatch_end(mhash)] = '\0';
213  if ((strcmp(linestr + mutt_regmatch_start(mhost), hostname) == 0) &&
214  (strcmp(linestr + mutt_regmatch_start(mhash), buf) == 0))
215  {
216  FREE(&linestr);
217  mutt_file_fclose(&fp);
218  return 1;
219  }
220  }
221  }
222 
223  mutt_file_fclose(&fp);
224 
225  /* not found a matching name */
226  return 0;
227 }
static void tls_fingerprint(gnutls_digest_algorithm_t algo, char *buf, size_t buflen, const gnutls_datum_t *data)
Create a fingerprint of a TLS Certificate.
Definition: gnutls.c:158
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:667
#H [foo.com] A76D ... 65B1
Definition: prex.h:109
Container for Accounts, Notifications.
Definition: neomutt.h:36
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
regmatch_t * mutt_prex_capture(enum Prex which, const char *str)
match a precompiled regex against a string
Definition: prex.c:301
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
static regoff_t mutt_regmatch_start(const regmatch_t *match)
Return the start of a match.
Definition: regex3.h:61
[#H foo.com A76D 954B EB79 1F49 5B3A 0A0E 0681 65B1]
Definition: prex.h:36
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define FREE(x)
Definition: memory.h:40
static regoff_t mutt_regmatch_end(const regmatch_t *match)
Return the end of a match.
Definition: regex3.h:71
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#H foo.com [A76D ... 65B1]
Definition: prex.h:110
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_compare_certificates()

static int tls_compare_certificates ( const gnutls_datum_t *  peercert)
static

Compare certificates against $certificate_file

Parameters
peercertCertificate
Return values
1Certificate matches file
0Error, or no match

Definition at line 235 of file gnutls.c.

236 {
237  gnutls_datum_t cert = { 0 };
238  unsigned char *ptr = NULL;
239  gnutls_datum_t b64_data = { 0 };
240  unsigned char *b64_data_data = NULL;
241  struct stat filestat;
242 
243  const char *const c_certificate_file =
244  cs_subset_path(NeoMutt->sub, "certificate_file");
245  if (stat(c_certificate_file, &filestat) == -1)
246  return 0;
247 
248  b64_data.size = filestat.st_size;
249  b64_data_data = mutt_mem_calloc(1, b64_data.size + 1);
250  b64_data.data = b64_data_data;
251 
252  FILE *fp = mutt_file_fopen(c_certificate_file, "r");
253  if (!fp)
254  return 0;
255 
256  b64_data.size = fread(b64_data.data, 1, b64_data.size, fp);
257  mutt_file_fclose(&fp);
258 
259  do
260  {
261  const int ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);
262  if (ret != 0)
263  {
264  FREE(&b64_data_data);
265  return 0;
266  }
267 
268  /* find start of cert, skipping junk */
269  ptr = (unsigned char *) strstr((char *) b64_data.data, CERT_SEP);
270  if (!ptr)
271  {
272  gnutls_free(cert.data);
273  FREE(&b64_data_data);
274  return 0;
275  }
276  /* find start of next cert */
277  ptr = (unsigned char *) strstr((char *) ptr + 1, CERT_SEP);
278 
279  b64_data.size = b64_data.size - (ptr - b64_data.data);
280  b64_data.data = ptr;
281 
282  if (cert.size == peercert->size)
283  {
284  if (memcmp(cert.data, peercert->data, cert.size) == 0)
285  {
286  /* match found */
287  gnutls_free(cert.data);
288  FREE(&b64_data_data);
289  return 1;
290  }
291  }
292 
293  gnutls_free(cert.data);
294  } while (ptr);
295 
296  /* no match found */
297  FREE(&b64_data_data);
298  return 0;
299 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Container for Accounts, Notifications.
Definition: neomutt.h:36
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define CERT_SEP
Definition: gnutls.c:61
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_check_preauth()

static int tls_check_preauth ( const gnutls_datum_t *  certdata,
gnutls_certificate_status_t  certstat,
const char *  hostname,
int  chainidx,
int *  certerr,
int *  savedcert 
)
static

Prepare a certificate for authentication.

Parameters
[in]certdataList of GnuTLS certificates
[in]certstatGnuTLS certificate status
[in]hostnameHostname
[in]chainidxIndex in the certificate chain
[out]certerrResult, e.g. CERTERR_VALID
[out]savedcert1 if certificate has been saved
Return values
0Success
-1Error

Definition at line 312 of file gnutls.c.

315 {
316  gnutls_x509_crt_t cert;
317 
318  *certerr = CERTERR_VALID;
319  *savedcert = 0;
320 
321  if (gnutls_x509_crt_init(&cert) < 0)
322  {
323  mutt_error(_("Error initialising gnutls certificate data"));
324  return -1;
325  }
326 
327  if (gnutls_x509_crt_import(cert, certdata, GNUTLS_X509_FMT_DER) < 0)
328  {
329  mutt_error(_("Error processing certificate data"));
330  gnutls_x509_crt_deinit(cert);
331  return -1;
332  }
333 
334  /* Note: tls_negotiate() contains a call to
335  * gnutls_certificate_set_verify_flags() with a flag disabling
336  * GnuTLS checking of the dates. So certstat shouldn't have the
337  * GNUTLS_CERT_EXPIRED and GNUTLS_CERT_NOT_ACTIVATED bits set. */
338  const bool c_ssl_verify_dates =
339  cs_subset_bool(NeoMutt->sub, "ssl_verify_dates");
340  if (c_ssl_verify_dates != MUTT_NO)
341  {
342  if (gnutls_x509_crt_get_expiration_time(cert) < mutt_date_epoch())
343  *certerr |= CERTERR_EXPIRED;
344  if (gnutls_x509_crt_get_activation_time(cert) > mutt_date_epoch())
345  *certerr |= CERTERR_NOTYETVALID;
346  }
347 
348  const bool c_ssl_verify_host =
349  cs_subset_bool(NeoMutt->sub, "ssl_verify_host");
350  if ((chainidx == 0) && (c_ssl_verify_host != MUTT_NO) &&
351  !gnutls_x509_crt_check_hostname(cert, hostname) &&
352  !tls_check_stored_hostname(certdata, hostname))
353  {
354  *certerr |= CERTERR_HOSTNAME;
355  }
356 
357  if (certstat & GNUTLS_CERT_REVOKED)
358  {
359  *certerr |= CERTERR_REVOKED;
360  certstat ^= GNUTLS_CERT_REVOKED;
361  }
362 
363  /* see whether certificate is in our cache (certificates file) */
364  if (tls_compare_certificates(certdata))
365  {
366  *savedcert = 1;
367 
368  /* We check above for certs with bad dates or that are revoked.
369  * These must be accepted manually each time. Otherwise, we
370  * accept saved certificates as valid. */
371  if (*certerr == CERTERR_VALID)
372  {
373  gnutls_x509_crt_deinit(cert);
374  return 0;
375  }
376  }
377 
378  if (certstat & GNUTLS_CERT_INVALID)
379  {
380  *certerr |= CERTERR_NOTTRUSTED;
381  certstat ^= GNUTLS_CERT_INVALID;
382  }
383 
384  if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND)
385  {
386  /* NB: already cleared if cert in cache */
387  *certerr |= CERTERR_NOTTRUSTED;
388  certstat ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
389  }
390 
391  if (certstat & GNUTLS_CERT_SIGNER_NOT_CA)
392  {
393  /* NB: already cleared if cert in cache */
394  *certerr |= CERTERR_SIGNERNOTCA;
395  certstat ^= GNUTLS_CERT_SIGNER_NOT_CA;
396  }
397 
398  if (certstat & GNUTLS_CERT_INSECURE_ALGORITHM)
399  {
400  /* NB: already cleared if cert in cache */
401  *certerr |= CERTERR_INSECUREALG;
402  certstat ^= GNUTLS_CERT_INSECURE_ALGORITHM;
403  }
404 
405  /* we've been zeroing the interesting bits in certstat -
406  * don't return OK if there are any unhandled bits we don't
407  * understand */
408  if (certstat != 0)
409  *certerr |= CERTERR_OTHER;
410 
411  gnutls_x509_crt_deinit(cert);
412 
413  if (*certerr == CERTERR_VALID)
414  return 0;
415 
416  return -1;
417 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define CERTERR_INSECUREALG
Definition: gnutls.c:55
#define mutt_error(...)
Definition: logging.h:88
static int tls_compare_certificates(const gnutls_datum_t *peercert)
Compare certificates against $certificate_file
Definition: gnutls.c:235
#define CERTERR_REVOKED
Definition: gnutls.c:51
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define CERTERR_EXPIRED
Definition: gnutls.c:49
#define CERTERR_NOTYETVALID
Definition: gnutls.c:50
#define CERTERR_HOSTNAME
Definition: gnutls.c:53
#define CERTERR_VALID
Definition: gnutls.c:48
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
#define CERTERR_NOTTRUSTED
Definition: gnutls.c:52
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
static int tls_check_stored_hostname(const gnutls_datum_t *cert, const char *hostname)
Does the hostname match a stored certificate?
Definition: gnutls.c:189
#define CERTERR_OTHER
Definition: gnutls.c:56
#define CERTERR_SIGNERNOTCA
Definition: gnutls.c:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_cert()

static void add_cert ( const char *  title,
gnutls_x509_crt_t  cert,
bool  issuer,
struct ListHead *  list 
)
static

Look up certificate info and save it to a list.

Parameters
titleTitle for this block of certificate info
certCertificate
issuerIf true, look up the issuer rather than owner details
listList to save info to

Definition at line 426 of file gnutls.c.

428 {
429  static const char *part[] = {
430  GNUTLS_OID_X520_COMMON_NAME, // CN
431  GNUTLS_OID_PKCS9_EMAIL, // Email
432  GNUTLS_OID_X520_ORGANIZATION_NAME, // O
433  GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, // OU
434  GNUTLS_OID_X520_LOCALITY_NAME, // L
435  GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, // ST
436  GNUTLS_OID_X520_COUNTRY_NAME, // C
437  };
438 
439  char buf[128];
440  int rc;
441 
442  // Allocate formatted strings and let the ListHead take ownership
443  mutt_list_insert_tail(list, mutt_str_dup(title));
444 
445  for (size_t i = 0; i < mutt_array_size(part); i++)
446  {
447  size_t buflen = sizeof(buf);
448  if (issuer)
449  rc = gnutls_x509_crt_get_issuer_dn_by_oid(cert, part[i], 0, 0, buf, &buflen);
450  else
451  rc = gnutls_x509_crt_get_dn_by_oid(cert, part[i], 0, 0, buf, &buflen);
452  if (rc != 0)
453  continue;
454 
455  char *line = NULL;
456  mutt_str_asprintf(&line, " %s", buf);
457  mutt_list_insert_tail(list, line);
458  }
459 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define mutt_array_size(x)
Definition: memory.h:33
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1128
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_check_one_certificate()

static int tls_check_one_certificate ( const gnutls_datum_t *  certdata,
gnutls_certificate_status_t  certstat,
const char *  hostname,
int  idx,
size_t  len 
)
static

Check a GnuTLS certificate.

Parameters
certdataList of GnuTLS certificates
certstatGnuTLS certificate status
hostnameHostname
idxIndex into certificate list
lenLength of certificate list
Return values
1Success
0Failure

Definition at line 471 of file gnutls.c.

474 {
475  struct ListHead list = STAILQ_HEAD_INITIALIZER(list);
476  int certerr, savedcert;
477  gnutls_x509_crt_t cert;
478  char fpbuf[128];
479  time_t t;
480  char datestr[30];
481  char title[256];
482  gnutls_datum_t pemdata = { 0 };
483 
484  if (tls_check_preauth(certdata, certstat, hostname, idx, &certerr, &savedcert) == 0)
485  return 1;
486 
487  /* interactive check from user */
488  if (gnutls_x509_crt_init(&cert) < 0)
489  {
490  mutt_error(_("Error initialising gnutls certificate data"));
491  return 0;
492  }
493 
494  if (gnutls_x509_crt_import(cert, certdata, GNUTLS_X509_FMT_DER) < 0)
495  {
496  mutt_error(_("Error processing certificate data"));
497  gnutls_x509_crt_deinit(cert);
498  return 0;
499  }
500 
501  add_cert(_("This certificate belongs to:"), cert, false, &list);
502  mutt_list_insert_tail(&list, NULL);
503  add_cert(_("This certificate was issued by:"), cert, true, &list);
504 
505  mutt_list_insert_tail(&list, NULL);
506  mutt_list_insert_tail(&list, mutt_str_dup(_("This certificate is valid")));
507 
508  char *line = NULL;
509  t = gnutls_x509_crt_get_activation_time(cert);
510  mutt_date_make_tls(datestr, sizeof(datestr), t);
511  mutt_str_asprintf(&line, _(" from %s"), datestr);
512  mutt_list_insert_tail(&list, line);
513 
514  t = gnutls_x509_crt_get_expiration_time(cert);
515  mutt_date_make_tls(datestr, sizeof(datestr), t);
516  mutt_str_asprintf(&line, _(" to %s"), datestr);
517  mutt_list_insert_tail(&list, line);
518  mutt_list_insert_tail(&list, NULL);
519 
520  fpbuf[0] = '\0';
521  tls_fingerprint(GNUTLS_DIG_SHA, fpbuf, sizeof(fpbuf), certdata);
522  mutt_str_asprintf(&line, _("SHA1 Fingerprint: %s"), fpbuf);
523  mutt_list_insert_tail(&list, line);
524  fpbuf[0] = '\0';
525  fpbuf[40] = '\0'; /* Ensure the second printed line is null terminated */
526  tls_fingerprint(GNUTLS_DIG_SHA256, fpbuf, sizeof(fpbuf), certdata);
527  fpbuf[39] = '\0'; /* Divide into two lines of output */
528  mutt_str_asprintf(&line, "%s%s", _("SHA256 Fingerprint: "), fpbuf);
529  mutt_list_insert_tail(&list, line);
530  mutt_str_asprintf(&line, "%*s%s", (int) mutt_str_len(_("SHA256 Fingerprint: ")),
531  "", fpbuf + 40);
532  mutt_list_insert_tail(&list, line);
533 
534  if (certerr)
535  mutt_list_insert_tail(&list, NULL);
536 
537  if (certerr & CERTERR_NOTYETVALID)
538  {
540  &list, mutt_str_dup(_("WARNING: Server certificate is not yet valid")));
541  }
542  if (certerr & CERTERR_EXPIRED)
543  {
545  &list, mutt_str_dup(_("WARNING: Server certificate has expired")));
546  }
547  if (certerr & CERTERR_REVOKED)
548  {
550  &list, mutt_str_dup(_("WARNING: Server certificate has been revoked")));
551  }
552  if (certerr & CERTERR_HOSTNAME)
553  {
555  &list,
556  mutt_str_dup(_("WARNING: Server hostname does not match certificate")));
557  }
558  if (certerr & CERTERR_SIGNERNOTCA)
559  {
561  &list,
562  mutt_str_dup(_("WARNING: Signer of server certificate is not a CA")));
563  }
564  if (certerr & CERTERR_INSECUREALG)
565  {
567  &list, mutt_str_dup(_("Warning: Server certificate was signed using "
568  "an insecure algorithm")));
569  }
570 
571  snprintf(title, sizeof(title),
572  _("SSL Certificate check (certificate %zu of %zu in chain)"), len - idx, len);
573 
574  const char *const c_certificate_file =
575  cs_subset_path(NeoMutt->sub, "certificate_file");
576  const bool allow_always =
577  (c_certificate_file && !savedcert &&
578  !(certerr & (CERTERR_EXPIRED | CERTERR_NOTYETVALID | CERTERR_REVOKED)));
579  int rc = dlg_verify_certificate(title, &list, allow_always, false);
580  if (rc == 3) // Accept always
581  {
582  bool saved = false;
583  FILE *fp = mutt_file_fopen(c_certificate_file, "a");
584  if (fp)
585  {
586  if (certerr & CERTERR_HOSTNAME) // Save hostname if necessary
587  {
588  fpbuf[0] = '\0';
589  tls_fingerprint(GNUTLS_DIG_MD5, fpbuf, sizeof(fpbuf), certdata);
590  fprintf(fp, "#H %s %s\n", hostname, fpbuf);
591  saved = true;
592  }
593  if (certerr ^ CERTERR_HOSTNAME) // Save the cert for all other errors
594  {
595  int rc2 = gnutls_pem_base64_encode_alloc("CERTIFICATE", certdata, &pemdata);
596  if (rc2 == 0)
597  {
598  if (fwrite(pemdata.data, pemdata.size, 1, fp) == 1)
599  {
600  saved = true;
601  }
602  gnutls_free(pemdata.data);
603  }
604  }
605  mutt_file_fclose(&fp);
606  }
607  if (!saved)
608  mutt_message(_("Certificate saved"));
609  else
610  mutt_error(_("Warning: Couldn't save certificate"));
611  }
612 
613  mutt_list_free(&list);
614  gnutls_x509_crt_deinit(cert);
615  return (rc > 1);
616 }
#define CERTERR_INSECUREALG
Definition: gnutls.c:55
static void tls_fingerprint(gnutls_digest_algorithm_t algo, char *buf, size_t buflen, const gnutls_datum_t *data)
Create a fingerprint of a TLS Certificate.
Definition: gnutls.c:158
#define mutt_error(...)
Definition: logging.h:88
size_t idx
Definition: mailbox.c:257
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define CERTERR_REVOKED
Definition: gnutls.c:51
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
static void add_cert(const char *title, gnutls_x509_crt_t cert, bool issuer, struct ListHead *list)
Look up certificate info and save it to a list.
Definition: gnutls.c:426
static int tls_check_preauth(const gnutls_datum_t *certdata, gnutls_certificate_status_t certstat, const char *hostname, int chainidx, int *certerr, int *savedcert)
Prepare a certificate for authentication.
Definition: gnutls.c:312
int mutt_date_make_tls(char *buf, size_t buflen, time_t timestamp)
Format date in TLS certificate verification style.
Definition: date.c:583
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define CERTERR_EXPIRED
Definition: gnutls.c:49
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
#define CERTERR_NOTYETVALID
Definition: gnutls.c:50
#define CERTERR_HOSTNAME
Definition: gnutls.c:53
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
int dlg_verify_certificate(const char *title, struct ListHead *list, bool allow_always, bool allow_skip)
Ask the user to validate the certificate.
Definition: dlgverifycert.c:92
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
#define mutt_message(...)
Definition: logging.h:87
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1128
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#define CERTERR_SIGNERNOTCA
Definition: gnutls.c:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_check_certificate()

static int tls_check_certificate ( struct Connection conn)
static

Check a connection's certificate.

Parameters
connConnection to a server
Return values
1Certificate is valid
0Error, or certificate is invalid

Definition at line 624 of file gnutls.c.

625 {
626  struct TlsSockData *data = conn->sockdata;
627  gnutls_session_t state = data->state;
628  const gnutls_datum_t *cert_list = NULL;
629  unsigned int cert_list_size = 0;
630  gnutls_certificate_status_t certstat;
631  int certerr, savedcert, rc = 0;
632  int max_preauth_pass = -1;
633 
634  /* tls_verify_peers() calls gnutls_certificate_verify_peers2(),
635  * which verifies the auth_type is GNUTLS_CRD_CERTIFICATE
636  * and that get_certificate_type() for the server is GNUTLS_CRT_X509.
637  * If it returns 0, certstat will be set with failure codes for the first
638  * cert in the chain(from CA to host) with an error.
639  */
640  if (tls_verify_peers(state, &certstat) != 0)
641  return 0;
642 
643  cert_list = gnutls_certificate_get_peers(state, &cert_list_size);
644  if (!cert_list)
645  {
646  mutt_error(_("Unable to get certificate from peer"));
647  return 0;
648  }
649 
650  /* tls_verify_peers doesn't check hostname or expiration, so walk
651  * from most specific to least checking these. If we see a saved certificate,
652  * its status short-circuits the remaining checks. */
653  int preauthrc = 0;
654  for (int i = 0; i < cert_list_size; i++)
655  {
656  rc = tls_check_preauth(&cert_list[i], certstat, conn->account.host, i,
657  &certerr, &savedcert);
658  preauthrc += rc;
659  if (!preauthrc)
660  max_preauth_pass = i;
661 
662  if (savedcert)
663  {
664  if (preauthrc == 0)
665  return 1;
666  break;
667  }
668  }
669 
670  /* then check interactively, starting from chain root */
671  for (int i = cert_list_size - 1; i >= 0; i--)
672  {
673  rc = tls_check_one_certificate(&cert_list[i], certstat, conn->account.host,
674  i, cert_list_size);
675 
676  /* Stop checking if the menu cert is aborted or rejected. */
677  if (rc == 0)
678  break;
679 
680  /* add signers to trust set, then reverify */
681  if (i)
682  {
683  int rcsettrust = gnutls_certificate_set_x509_trust_mem(
684  data->xcred, &cert_list[i], GNUTLS_X509_FMT_DER);
685  if (rcsettrust != 1)
686  mutt_debug(LL_DEBUG1, "error trusting certificate %d: %d\n", i, rcsettrust);
687 
688  if (tls_verify_peers(state, &certstat) != 0)
689  return 0;
690 
691  /* If the cert chain now verifies, and all lower certs already
692  * passed preauth, we are done. */
693  if (!certstat && (max_preauth_pass >= (i - 1)))
694  return 1;
695  }
696  }
697 
698  return rc;
699 }
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
#define mutt_error(...)
Definition: logging.h:88
void * sockdata
Backend-specific socket data.
Definition: connection.h:46
#define _(a)
Definition: message.h:28
static int tls_check_one_certificate(const gnutls_datum_t *certdata, gnutls_certificate_status_t certstat, const char *hostname, int idx, size_t len)
Check a GnuTLS certificate.
Definition: gnutls.c:471
gnutls_session_t state
Definition: gnutls.c:81
char host[128]
Server to login to.
Definition: connaccount.h:53
static int tls_check_preauth(const gnutls_datum_t *certdata, gnutls_certificate_status_t certstat, const char *hostname, int chainidx, int *certerr, int *savedcert)
Prepare a certificate for authentication.
Definition: gnutls.c:312
gnutls_certificate_credentials_t xcred
Definition: gnutls.c:82
TLS socket data -.
Definition: gnutls.c:79
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
static int tls_verify_peers(gnutls_session_t tlsstate, gnutls_certificate_status_t *certstat)
Wrapper for gnutls_certificate_verify_peers()
Definition: gnutls.c:120
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_get_client_cert()

static void tls_get_client_cert ( struct Connection conn)
static

Get the client certificate for a TLS connection.

Parameters
connConnection to a server
Note
This function grabs the CN out of the client cert but appears to do nothing with it. It does contain a call to mutt_account_getuser().

Definition at line 708 of file gnutls.c.

709 {
710  struct TlsSockData *data = conn->sockdata;
711  gnutls_x509_crt_t clientcrt;
712  char *cn = NULL;
713  size_t cnlen = 0;
714  int rc;
715 
716  /* get our cert CN if we have one */
717  const gnutls_datum_t *crtdata = gnutls_certificate_get_ours(data->state);
718  if (!crtdata)
719  return;
720 
721  if (gnutls_x509_crt_init(&clientcrt) < 0)
722  {
723  mutt_debug(LL_DEBUG1, "Failed to init gnutls crt\n");
724  return;
725  }
726 
727  if (gnutls_x509_crt_import(clientcrt, crtdata, GNUTLS_X509_FMT_DER) < 0)
728  {
729  mutt_debug(LL_DEBUG1, "Failed to import gnutls client crt\n");
730  goto err;
731  }
732 
733  /* get length of CN, then grab it. */
734  rc = gnutls_x509_crt_get_dn_by_oid(clientcrt, GNUTLS_OID_X520_COMMON_NAME, 0,
735  0, NULL, &cnlen);
736  if (((rc >= 0) || (rc == GNUTLS_E_SHORT_MEMORY_BUFFER)) && (cnlen > 0))
737  {
738  cn = mutt_mem_calloc(1, cnlen);
739  if (gnutls_x509_crt_get_dn_by_oid(clientcrt, GNUTLS_OID_X520_COMMON_NAME, 0,
740  0, cn, &cnlen) < 0)
741  {
742  goto err;
743  }
744  mutt_debug(LL_DEBUG2, "client certificate CN: %s\n", cn);
745 
746  /* if we are using a client cert, SASL may expect an external auth name */
747  if (mutt_account_getuser(&conn->account) < 0)
748  mutt_debug(LL_DEBUG1, "Couldn't get user info\n");
749  }
750 
751 err:
752  FREE(&cn);
753  gnutls_x509_crt_deinit(clientcrt);
754 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:47
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
void * sockdata
Backend-specific socket data.
Definition: connection.h:46
gnutls_session_t state
Definition: gnutls.c:81
Log at debug level 2.
Definition: logging.h:41
TLS socket data -.
Definition: gnutls.c:79
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_set_priority()

static int tls_set_priority ( struct TlsSockData data)
static

Set the priority of various protocols.

Parameters
dataTLS socket data
Return values
0Success
-1Error

Definition at line 839 of file gnutls.c.

840 {
841  size_t nproto = 0; /* number of tls/ssl protocols */
842 
843  const bool c_ssl_use_tlsv1_2 =
844  cs_subset_bool(NeoMutt->sub, "ssl_use_tlsv1_2");
845  if (c_ssl_use_tlsv1_2)
846  protocol_priority[nproto++] = GNUTLS_TLS1_2;
847  const bool c_ssl_use_tlsv1_1 =
848  cs_subset_bool(NeoMutt->sub, "ssl_use_tlsv1_1");
849  if (c_ssl_use_tlsv1_1)
850  protocol_priority[nproto++] = GNUTLS_TLS1_1;
851  const bool c_ssl_use_tlsv1 = cs_subset_bool(NeoMutt->sub, "ssl_use_tlsv1");
852  if (c_ssl_use_tlsv1)
853  protocol_priority[nproto++] = GNUTLS_TLS1;
854  const bool c_ssl_use_sslv3 = cs_subset_bool(NeoMutt->sub, "ssl_use_sslv3");
855  if (c_ssl_use_sslv3)
856  protocol_priority[nproto++] = GNUTLS_SSL3;
857  protocol_priority[nproto] = 0;
858 
859  if (nproto == 0)
860  {
861  mutt_error(_("All available protocols for TLS/SSL connection disabled"));
862  return -1;
863  }
864 
865  const char *const c_ssl_ciphers =
866  cs_subset_string(NeoMutt->sub, "ssl_ciphers");
867  if (c_ssl_ciphers)
868  {
869  mutt_error(
870  _("Explicit ciphersuite selection via $ssl_ciphers not supported"));
871  }
872 
873  /* We use default priorities (see gnutls documentation),
874  * except for protocol version */
875  gnutls_set_default_priority(data->state);
876  gnutls_protocol_set_priority(data->state, protocol_priority);
877  return 0;
878 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define mutt_error(...)
Definition: logging.h:88
#define _(a)
Definition: message.h:28
gnutls_session_t state
Definition: gnutls.c:81
Container for Accounts, Notifications.
Definition: neomutt.h:36
static int protocol_priority[]
Definition: gnutls.c:72
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tls_negotiate()

static int tls_negotiate ( struct Connection conn)
static

Negotiate TLS connection.

Parameters
connConnection to a server
Return values
0Success
-1Error

After TLS state has been initialized, attempt to negotiate TLS over the wire, including certificate checks.

Definition at line 890 of file gnutls.c.

891 {
892  struct TlsSockData *data = mutt_mem_calloc(1, sizeof(struct TlsSockData));
893  conn->sockdata = data;
894  int err = gnutls_certificate_allocate_credentials(&data->xcred);
895  if (err < 0)
896  {
897  FREE(&conn->sockdata);
898  mutt_error("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
899  return -1;
900  }
901 
902  const char *const c_certificate_file =
903  cs_subset_path(NeoMutt->sub, "certificate_file");
904  gnutls_certificate_set_x509_trust_file(data->xcred, c_certificate_file, GNUTLS_X509_FMT_PEM);
905  /* ignore errors, maybe file doesn't exist yet */
906 
907  const char *const c_ssl_ca_certificates_file =
908  cs_subset_path(NeoMutt->sub, "ssl_ca_certificates_file");
909  if (c_ssl_ca_certificates_file)
910  {
911  gnutls_certificate_set_x509_trust_file(data->xcred, c_ssl_ca_certificates_file,
912  GNUTLS_X509_FMT_PEM);
913  }
914 
915  const char *const c_ssl_client_cert =
916  cs_subset_path(NeoMutt->sub, "ssl_client_cert");
917  if (c_ssl_client_cert)
918  {
919  mutt_debug(LL_DEBUG2, "Using client certificate %s\n", c_ssl_client_cert);
920  gnutls_certificate_set_x509_key_file(data->xcred, c_ssl_client_cert,
921  c_ssl_client_cert, GNUTLS_X509_FMT_PEM);
922  }
923 
924 #ifdef HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS
925  /* disable checking certificate activation/expiration times
926  * in gnutls, we do the checks ourselves */
927  gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
928 #endif
929 
930  err = gnutls_init(&data->state, GNUTLS_CLIENT);
931  if (err)
932  {
933  mutt_error("gnutls_init: %s", gnutls_strerror(err));
934  goto fail;
935  }
936 
937  /* set socket */
938  gnutls_transport_set_ptr(data->state, (gnutls_transport_ptr_t) (long) conn->fd);
939 
940  if (gnutls_server_name_set(data->state, GNUTLS_NAME_DNS, conn->account.host,
941  mutt_str_len(conn->account.host)))
942  {
943  mutt_error(_("Warning: unable to set TLS SNI host name"));
944  }
945 
946  if (tls_set_priority(data) < 0)
947  {
948  goto fail;
949  }
950 
951  const short c_ssl_min_dh_prime_bits =
952  cs_subset_number(NeoMutt->sub, "ssl_min_dh_prime_bits");
953  if (c_ssl_min_dh_prime_bits > 0)
954  {
955  gnutls_dh_set_prime_bits(data->state, c_ssl_min_dh_prime_bits);
956  }
957 
958  gnutls_credentials_set(data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);
959 
960  do
961  {
962  err = gnutls_handshake(data->state);
963  } while ((err == GNUTLS_E_AGAIN) || (err == GNUTLS_E_INTERRUPTED));
964 
965  if (err < 0)
966  {
967  if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
968  {
969  mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),
970  gnutls_alert_get_name(gnutls_alert_get(data->state)));
971  }
972  else
973  {
974  mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
975  }
976  goto fail;
977  }
978 
979  if (tls_check_certificate(conn) == 0)
980  goto fail;
981 
982  /* set Security Strength Factor (SSF) for SASL */
983  /* NB: gnutls_cipher_get_key_size() returns key length in bytes */
984  conn->ssf = gnutls_cipher_get_key_size(gnutls_cipher_get(data->state)) * 8;
985 
986  tls_get_client_cert(conn);
987 
988  if (!OptNoCurses)
989  {
990  mutt_message(_("SSL/TLS connection using %s (%s/%s/%s)"),
991  gnutls_protocol_get_name(gnutls_protocol_get_version(data->state)),
992  gnutls_kx_get_name(gnutls_kx_get(data->state)),
993  gnutls_cipher_get_name(gnutls_cipher_get(data->state)),
994  gnutls_mac_get_name(gnutls_mac_get(data->state)));
995  mutt_sleep(0);
996  }
997 
998  return 0;
999 
1000 fail:
1001  gnutls_certificate_free_credentials(data->xcred);
1002  gnutls_deinit(data->state);
1003  FREE(&conn->sockdata);
1004  return -1;
1005 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
unsigned int ssf
Security strength factor, in bits (see below)
Definition: connection.h:41
#define mutt_error(...)
Definition: logging.h:88
void * sockdata
Backend-specific socket data.
Definition: connection.h:46
static void tls_get_client_cert(struct Connection *conn)
Get the client certificate for a TLS connection.
Definition: gnutls.c:708
#define _(a)
Definition: message.h:28
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:47
gnutls_session_t state
Definition: gnutls.c:81
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
static int tls_set_priority(struct TlsSockData *data)
Set the priority of various protocols.
Definition: gnutls.c:839
static int tls_check_certificate(struct Connection *conn)
Check a connection&#39;s certificate.
Definition: gnutls.c:624
char host[128]
Server to login to.
Definition: connaccount.h:53
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1461
Log at debug level 2.
Definition: logging.h:41
gnutls_certificate_credentials_t xcred
Definition: gnutls.c:82
TLS socket data -.
Definition: gnutls.c:79
int fd
Socket file descriptor.
Definition: connection.h:44
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_ssl_socket_setup()

int mutt_ssl_socket_setup ( struct Connection conn)

Set up SSL socket mulitplexor.

Parameters
connConnection to a server
Return values
0Success
-1Error

Definition at line 1147 of file gnutls.c.

1148 {
1149  if (tls_init() < 0)
1150  return -1;
1151 
1152  conn->open = tls_socket_open;
1153  conn->read = tls_socket_read;
1154  conn->write = tls_socket_write;
1155  conn->close = tls_socket_close;
1156  conn->poll = tls_socket_poll;
1157 
1158  return 0;
1159 }
static int tls_socket_open(struct Connection *conn)
Open a TLS socket - Implements Connection::open() -.
Definition: gnutls.c:1050
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:82
static int tls_socket_poll(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block - Implements Connection::poll() -.
Definition: gnutls.c:1010
int(* open)(struct Connection *conn)
Definition: connection.h:69
static int tls_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a TLS socket - Implements Connection::write() -.
Definition: gnutls.c:1094
static int tls_socket_close(struct Connection *conn)
Close a TLS socket - Implements Connection::close() -.
Definition: gnutls.c:1025
int(* close)(struct Connection *conn)
Definition: connection.h:119
static int tls_socket_read(struct Connection *conn, char *buf, size_t count)
Read data from a TLS socket - Implements Connection::read() -.
Definition: gnutls.c:1067
static int tls_init(void)
Set up Gnu TLS.
Definition: gnutls.c:90
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:108
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:95
+ Here is the caller graph for this function:

◆ mutt_ssl_starttls()

int mutt_ssl_starttls ( struct Connection conn)

Negotiate TLS over an already opened connection.

Parameters
connConnection to a server
Return values
0Success
-1Error

Definition at line 1167 of file gnutls.c.

1168 {
1169  if (tls_init() < 0)
1170  return -1;
1171 
1172  if (tls_negotiate(conn) < 0)
1173  return -1;
1174 
1175  conn->read = tls_socket_read;
1176  conn->write = tls_socket_write;
1177  conn->close = tls_starttls_close;
1178  conn->poll = tls_socket_poll;
1179 
1180  return 0;
1181 }
int(* read)(struct Connection *conn, char *buf, size_t count)
Definition: connection.h:82
static int tls_socket_poll(struct Connection *conn, time_t wait_secs)
Check whether a socket read would block - Implements Connection::poll() -.
Definition: gnutls.c:1010
static int tls_negotiate(struct Connection *conn)
Negotiate TLS connection.
Definition: gnutls.c:890
static int tls_socket_write(struct Connection *conn, const char *buf, size_t count)
Write data to a TLS socket - Implements Connection::write() -.
Definition: gnutls.c:1094
int(* close)(struct Connection *conn)
Definition: connection.h:119
static int tls_socket_read(struct Connection *conn, char *buf, size_t count)
Read data from a TLS socket - Implements Connection::read() -.
Definition: gnutls.c:1067
static int tls_init(void)
Set up Gnu TLS.
Definition: gnutls.c:90
int(* poll)(struct Connection *conn, time_t wait_secs)
Definition: connection.h:108
int(* write)(struct Connection *conn, const char *buf, size_t count)
Definition: connection.h:95
static int tls_starttls_close(struct Connection *conn)
Close a TLS connection - Implements Connection::close() -.
Definition: gnutls.c:1128
+ Here is the caller graph for this function:

Variable Documentation

◆ dialog_row_len

const int dialog_row_len = 128

Definition at line 59 of file gnutls.c.

◆ protocol_priority

int protocol_priority[]
static
Initial value:
= { GNUTLS_TLS1_2, GNUTLS_TLS1_1, GNUTLS_TLS1,
GNUTLS_SSL3, 0 }

Definition at line 72 of file gnutls.c.