⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mutt_ssl_gnutls.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2001 Marco d'Itri <md@linux.it> * Copyright (C) 2001-2004 Andrew McDonald <andrew@mcdonald.org.uk> * *     This program is free software; you can redistribute it and/or modify *     it under the terms of the GNU General Public License as published by *     the Free Software Foundation; either version 2 of the License, or *     (at your option) any later version. * *     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, write to the Free Software *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */#if HAVE_CONFIG_H# include "config.h"#endif#include <gnutls/gnutls.h>#include <gnutls/x509.h>#ifdef HAVE_GNUTLS_OPENSSL_H#include <gnutls/openssl.h>#endif#include "mutt.h"#include "mutt_socket.h"#include "mutt_curses.h"#include "mutt_menu.h"#include "mutt_ssl.h"#include "mutt_regex.h"typedef struct _tlssockdata{  gnutls_session state;  gnutls_certificate_credentials xcred;}tlssockdata;/* local prototypes */static int tls_socket_read (CONNECTION* conn, char* buf, size_t len);static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len);static int tls_socket_open (CONNECTION* conn);static int tls_socket_close (CONNECTION* conn);static int tls_starttls_close (CONNECTION* conn);static int tls_init (void);static int tls_negotiate (CONNECTION* conn);static int tls_check_certificate (CONNECTION* conn);static int tls_init (void){  static unsigned char init_complete = 0;  int err;  if (init_complete)    return 0;  err = gnutls_global_init();  if (err < 0)  {    mutt_error ("gnutls_global_init: %s", gnutls_strerror(err));    mutt_sleep (2);    return -1;  }  init_complete = 1;  return 0;}int mutt_ssl_socket_setup (CONNECTION* conn){  if (tls_init() < 0)    return -1;  conn->conn_open	= tls_socket_open;  conn->conn_read	= tls_socket_read;  conn->conn_write	= tls_socket_write;  conn->conn_close	= tls_socket_close;  conn->conn_poll       = raw_socket_poll;  return 0;}static int tls_socket_read (CONNECTION* conn, char* buf, size_t len){  tlssockdata *data = conn->sockdata;  int ret;  if (!data)  {    mutt_error (_("Error: no TLS socket open"));    mutt_sleep (2);    return -1;  }  ret = gnutls_record_recv (data->state, buf, len);  if (gnutls_error_is_fatal(ret) == 1)  {    mutt_error ("tls_socket_read (%s)", gnutls_strerror (ret));    mutt_sleep (4);    return -1;  }  return ret;}static int tls_socket_write (CONNECTION* conn, const char* buf, size_t len){  tlssockdata *data = conn->sockdata;  int ret;  if (!data)  {    mutt_error (_("Error: no TLS socket open"));    mutt_sleep (2);    return -1;  }  ret = gnutls_record_send (data->state, buf, len);  if (gnutls_error_is_fatal(ret) == 1)  {    mutt_error ("tls_socket_write (%s)", gnutls_strerror (ret));    mutt_sleep (4);    return -1;  }  return ret;}static int tls_socket_open (CONNECTION* conn){  if (raw_socket_open (conn) < 0)    return -1;  if (tls_negotiate (conn) < 0)  {    tls_socket_close (conn);    return -1;  }  return 0;}int mutt_ssl_starttls (CONNECTION* conn){  if (tls_init() < 0)    return -1;  if (tls_negotiate (conn) < 0)    return -1;  conn->conn_read	= tls_socket_read;  conn->conn_write	= tls_socket_write;  conn->conn_close	= tls_starttls_close;  return 0;}static int protocol_priority[] = {GNUTLS_TLS1, GNUTLS_SSL3, 0};/* tls_negotiate: After TLS state has been initialised, attempt to negotiate *   TLS over the wire, including certificate checks. */static int tls_negotiate (CONNECTION * conn){  tlssockdata *data;  int err;  data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata));  conn->sockdata = data;  err = gnutls_certificate_allocate_credentials (&data->xcred);  if (err < 0)  {    FREE(&conn->sockdata);    mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));    mutt_sleep (2);    return -1;  }  gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile,					  GNUTLS_X509_FMT_PEM);  /* ignore errors, maybe file doesn't exist yet */  if (SslCACertFile)  {    gnutls_certificate_set_x509_trust_file (data->xcred, SslCACertFile,                                            GNUTLS_X509_FMT_PEM);  }/*  gnutls_set_x509_client_key (data->xcred, "", "");  gnutls_set_x509_cert_callback (data->xcred, cert_callback);*/  gnutls_init(&data->state, GNUTLS_CLIENT);  /* set socket */  gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd);  /* disable TLS/SSL protocols as needed */  if (!option(OPTTLSV1) && !option(OPTSSLV3))  {    mutt_error (_("All available protocols for TLS/SSL connection disabled"));    goto fail;  }  else if (!option(OPTTLSV1))  {    protocol_priority[0] = GNUTLS_SSL3;    protocol_priority[1] = 0;  }  else if (!option(OPTSSLV3))  {    protocol_priority[0] = GNUTLS_TLS1;    protocol_priority[1] = 0;  }  /*  else    use the list set above  */  /* We use default priorities (see gnutls documentation),     except for protocol version */  gnutls_set_default_priority (data->state);  gnutls_protocol_set_priority (data->state, protocol_priority);  if (SslDHPrimeBits > 0)  {    gnutls_dh_set_prime_bits (data->state, SslDHPrimeBits);  }/*  gnutls_set_cred (data->state, GNUTLS_ANON, NULL);*/  gnutls_credentials_set (data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);  err = gnutls_handshake(data->state);  while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)  {    err = gnutls_handshake(data->state);  }  if (err < 0) {    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)    {      mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),		 gnutls_alert_get_name(gnutls_alert_get(data->state)));    }    else    {      mutt_error("gnutls_handshake: %s", gnutls_strerror(err));    }    mutt_sleep (2);    goto fail;  }  if (!tls_check_certificate(conn))    goto fail;  /* set Security Strength Factor (SSF) for SASL */  /* NB: gnutls_cipher_get_key_size() returns key length in bytes */  conn->ssf = gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8;  mutt_message (_("SSL/TLS connection using %s (%s/%s/%s)"),		gnutls_protocol_get_name (gnutls_protocol_get_version (data->state)),		gnutls_kx_get_name (gnutls_kx_get (data->state)),		gnutls_cipher_get_name (gnutls_cipher_get (data->state)),		gnutls_mac_get_name (gnutls_mac_get (data->state)));  mutt_sleep (0);  return 0; fail:  gnutls_certificate_free_credentials (data->xcred);  gnutls_deinit (data->state);  FREE(&conn->sockdata);  return -1;}static int tls_socket_close (CONNECTION* conn){  tlssockdata *data = conn->sockdata;  if (data)  {    gnutls_bye (data->state, GNUTLS_SHUT_RDWR);    gnutls_certificate_free_credentials (data->xcred);    gnutls_deinit (data->state);    FREE (&conn->sockdata);  }  return raw_socket_close (conn);}static int tls_starttls_close (CONNECTION* conn){  int rc;  rc = tls_socket_close (conn);  conn->conn_read = raw_socket_read;  conn->conn_write = raw_socket_write;  conn->conn_close = raw_socket_close;  return rc;}#define CERT_SEP "-----BEGIN"/* this bit is based on read_ca_file() in gnutls */static int tls_compare_certificates (const gnutls_datum *peercert){  gnutls_datum cert;  unsigned char *ptr;  FILE *fd1;  int ret;  gnutls_datum b64_data;  unsigned char *b64_data_data;  struct stat filestat;  if (stat(SslCertFile, &filestat) == -1)    return 0;  b64_data.size = filestat.st_size+1;  b64_data_data = (unsigned char *) safe_calloc (1, b64_data.size);  b64_data_data[b64_data.size-1] = '\0';  b64_data.data = b64_data_data;  fd1 = fopen(SslCertFile, "r");  if (fd1 == NULL) {    return 0;  }  b64_data.size = fread(b64_data.data, 1, b64_data.size, fd1);  fclose(fd1);  do {    ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);    if (ret != 0)    {      FREE (&b64_data_data);      return 0;    }    ptr = (unsigned char *)strstr((char*)b64_data.data, CERT_SEP) + 1;    ptr = (unsigned char *)strstr((char*)ptr, CERT_SEP);    b64_data.size = b64_data.size - (ptr - b64_data.data);    b64_data.data = ptr;    if (cert.size == peercert->size)    {      if (memcmp (cert.data, peercert->data, cert.size) == 0)      {	/* match found */        gnutls_free(cert.data);	FREE (&b64_data_data);	return 1;      }    }    gnutls_free(cert.data);  } while (ptr != NULL);  /* no match found */  FREE (&b64_data_data);  return 0;}static void tls_fingerprint (gnutls_digest_algorithm algo,                             char* s, int l, const gnutls_datum* data){  unsigned char md[36];  size_t n;  int j;  n = 36;  if (gnutls_fingerprint (algo, data, (char *)md, &n) < 0)  {    snprintf (s, l, _("[unable to calculate]"));  }  else  {    for (j = 0; j < (int) n; j++)    {      char ch[8];      snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : ""));      safe_strcat (s, l, ch);    }    s[2*n+n/2-1] = '\0'; /* don't want trailing space */  }}static char *tls_make_date (time_t t, char *s, size_t len){  struct tm *l = gmtime (&t);  if (l)    snprintf (s, len,  "%s, %d %s %d %02d:%02d:%02d UTC",	      Weekdays[l->tm_wday], l->tm_mday, Months[l->tm_mon],	      l->tm_year + 1900, l->tm_hour, l->tm_min, l->tm_sec);  else    strfcpy (s, _("[invalid date]"), len);  return (s);}static int tls_check_stored_hostname (const gnutls_datum *cert,                                      const char *hostname){  char buf[80];  FILE *fp;  char *linestr = NULL;  size_t linestrsize;  int linenum = 0;  regex_t preg;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -