/*
* Copyright (C) 1999-2001 Tommi Komulainen <Tommi.Komulainen@iki.fi>
*
* 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 <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/x509_vfy.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
/* LibreSSL defines OPENSSL_VERSION_NUMBER but sets it to 0x20000000L.
* So technically we don't need the defined(OPENSSL_VERSION_NUMBER) check.
*/
#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
#define X509_get0_notBefore X509_get_notBefore
#define X509_get0_notAfter X509_get_notAfter
#define X509_getm_notBefore X509_get_notBefore
#define X509_getm_notAfter X509_get_notAfter
#define X509_STORE_CTX_get0_chain X509_STORE_CTX_get_chain
#endif
#undef _
#include <string.h>
#include "mutt.h"
#include "mutt_socket.h"
#include "mutt_menu.h"
#include "mutt_curses.h"
#include "mutt_ssl.h"
#include "mutt_idna.h"
/* Just in case OpenSSL doesn't define DEVRANDOM */
#ifndef DEVRANDOM
#define DEVRANDOM "/dev/urandom"
#endif
/* This is ugly, but as RAND_status came in on OpenSSL version 0.9.5
* and the code has to support older versions too, this is seemed to
* be cleaner way compared to having even uglier #ifdefs all around.
*/
#ifdef HAVE_RAND_STATUS
#define HAVE_ENTROPY() (RAND_status() == 1)
#else
static int entropy_byte_count = 0;
/* OpenSSL fills the entropy pool from /dev/urandom if it exists */
#define HAVE_ENTROPY() (!access(DEVRANDOM, R_OK) || entropy_byte_count >= 16)
#endif
/* index for storing hostname as application specific data in SSL structure */
static int HostExDataIndex = -1;
/* Index for storing the "skip mode" state in SSL structure. When the
* user skips a certificate in the chain, the stored value will be
* non-null. */
static int SkipModeExDataIndex = -1;
/* keep a handle on accepted certificates in case we want to
* open up another connection to the same server in this session */
static STACK_OF(X509) *SslSessionCerts = NULL;
typedef struct
{
SSL_CTX *ctx;
SSL *ssl;
X509 *cert;
unsigned char isopen;
}
sslsockdata;
/* local prototypes */
static int ssl_init (void);
static int add_entropy (const char *file);
static int ssl_socket_read (CONNECTION* conn, char* buf, size_t len);
static int ssl_socket_write (CONNECTION* conn, const char* buf, size_t len);
static int