2015-06-18 20:31:33 +02:00
|
|
|
import sys
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import ssl
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
import hashlib
|
2019-03-27 03:08:37 +01:00
|
|
|
import random
|
2015-06-18 20:31:33 +02:00
|
|
|
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
from Config import config
|
2015-09-27 02:08:53 +02:00
|
|
|
from util import helper
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
|
2015-06-18 20:31:33 +02:00
|
|
|
|
Version 0.3.1, rev238, Connection encryption using TLS, One click site clone feature, Encryption stats, Disable encryption startup parameter, Disable ssl compression startup parameter, Exchange supported encryption methods at handshake, Alternative open port checker, Option to store site privatekey in users.json, Torrent tracker swap, Test for bip32 based site creation, cloning and sslcert creation, Fix for Chrome plugin on OSX, Separate siteSign websocket command, Update pybitcointools to major speedup, Re-add sslwrap for python 0.2.9+, Disable SSL compression to save memory and better performance
2015-06-10 00:29:30 +02:00
|
|
|
class CryptConnectionManager:
|
2015-07-12 20:36:46 +02:00
|
|
|
def __init__(self):
|
2020-02-20 17:23:00 +01:00
|
|
|
if config.openssl_bin_file:
|
|
|
|
self.openssl_bin = config.openssl_bin_file
|
|
|
|
elif sys.platform.startswith("win"):
|
|
|
|
self.openssl_bin = "tools\\openssl\\openssl.exe"
|
|
|
|
elif config.dist_type.startswith("bundle_linux"):
|
|
|
|
self.openssl_bin = "../runtime/bin/openssl"
|
2015-07-12 20:36:46 +02:00
|
|
|
else:
|
2020-02-20 17:23:00 +01:00
|
|
|
self.openssl_bin = "openssl"
|
2019-09-04 20:16:32 +02:00
|
|
|
|
2019-12-17 14:22:29 +01:00
|
|
|
self.context_client = None
|
|
|
|
self.context_server = None
|
|
|
|
|
2019-10-24 03:09:16 +02:00
|
|
|
self.openssl_conf_template = "src/lib/openssl/openssl.cnf"
|
|
|
|
self.openssl_conf = config.data_dir + "/openssl.cnf"
|
|
|
|
|
2019-03-29 02:29:32 +01:00
|
|
|
self.openssl_env = {
|
2019-10-24 03:09:16 +02:00
|
|
|
"OPENSSL_CONF": self.openssl_conf,
|
2019-03-29 02:29:32 +01:00
|
|
|
"RANDFILE": config.data_dir + "/openssl-rand.tmp"
|
|
|
|
}
|
2015-07-12 20:36:46 +02:00
|
|
|
|
|
|
|
self.crypt_supported = [] # Supported cryptos
|
|
|
|
|
2019-03-27 03:08:37 +01:00
|
|
|
self.cacert_pem = config.data_dir + "/cacert-rsa.pem"
|
|
|
|
self.cakey_pem = config.data_dir + "/cakey-rsa.pem"
|
|
|
|
self.cert_pem = config.data_dir + "/cert-rsa.pem"
|
|
|
|
self.cert_csr = config.data_dir + "/cert-rsa.csr"
|
|
|
|
self.key_pem = config.data_dir + "/key-rsa.pem"
|
|
|
|
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log = logging.getLogger("CryptConnectionManager")
|
2019-08-15 03:08:40 +02:00
|
|
|
self.log.debug("Version: %s" % ssl.OPENSSL_VERSION)
|
|
|
|
|
|
|
|
self.fakedomains = [
|
|
|
|
"yahoo.com", "amazon.com", "live.com", "microsoft.com", "mail.ru", "csdn.net", "bing.com",
|
|
|
|
"amazon.co.jp", "office.com", "imdb.com", "msn.com", "samsung.com", "huawei.com", "ztedevices.com",
|
|
|
|
"godaddy.com", "w3.org", "gravatar.com", "creativecommons.org", "hatena.ne.jp",
|
|
|
|
"adobe.com", "opera.com", "apache.org", "rambler.ru", "one.com", "nationalgeographic.com",
|
|
|
|
"networksolutions.com", "php.net", "python.org", "phoca.cz", "debian.org", "ubuntu.com",
|
|
|
|
"nazwa.pl", "symantec.com"
|
|
|
|
]
|
|
|
|
|
|
|
|
def createSslContexts(self):
|
2019-12-17 14:22:29 +01:00
|
|
|
if self.context_server and self.context_client:
|
|
|
|
return False
|
2019-08-15 03:08:40 +02:00
|
|
|
ciphers = "ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:AES128-SHA256:AES256-SHA:"
|
|
|
|
ciphers += "!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK"
|
|
|
|
|
|
|
|
if hasattr(ssl, "PROTOCOL_TLS"):
|
|
|
|
protocol = ssl.PROTOCOL_TLS
|
|
|
|
else:
|
|
|
|
protocol = ssl.PROTOCOL_TLSv1_2
|
|
|
|
self.context_client = ssl.SSLContext(protocol)
|
|
|
|
self.context_client.check_hostname = False
|
|
|
|
self.context_client.verify_mode = ssl.CERT_NONE
|
|
|
|
|
|
|
|
self.context_server = ssl.SSLContext(protocol)
|
|
|
|
self.context_server.load_cert_chain(self.cert_pem, self.key_pem)
|
|
|
|
|
|
|
|
for ctx in (self.context_client, self.context_server):
|
|
|
|
ctx.set_ciphers(ciphers)
|
|
|
|
ctx.options |= ssl.OP_NO_COMPRESSION
|
|
|
|
try:
|
|
|
|
ctx.set_alpn_protocols(["h2", "http/1.1"])
|
|
|
|
ctx.set_npn_protocols(["h2", "http/1.1"])
|
|
|
|
except Exception:
|
|
|
|
pass
|
2019-07-18 03:33:35 +02:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
# Select crypt that supported by both sides
|
|
|
|
# Return: Name of the crypto
|
|
|
|
def selectCrypt(self, client_supported):
|
|
|
|
for crypt in self.crypt_supported:
|
|
|
|
if crypt in client_supported:
|
|
|
|
return crypt
|
|
|
|
return False
|
|
|
|
|
|
|
|
# Wrap socket for crypt
|
|
|
|
# Return: wrapped socket
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
def wrapSocket(self, sock, crypt, server=False, cert_pin=None):
|
2015-07-12 20:36:46 +02:00
|
|
|
if crypt == "tls-rsa":
|
|
|
|
if server:
|
2019-08-15 03:19:05 +02:00
|
|
|
sock_wrapped = self.context_server.wrap_socket(sock, server_side=True)
|
2015-07-12 20:36:46 +02:00
|
|
|
else:
|
2019-08-15 03:08:40 +02:00
|
|
|
sock_wrapped = self.context_client.wrap_socket(sock, server_hostname=random.choice(self.fakedomains))
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
if cert_pin:
|
|
|
|
cert_hash = hashlib.sha256(sock_wrapped.getpeercert(True)).hexdigest()
|
2019-07-03 18:35:55 +02:00
|
|
|
if cert_hash != cert_pin:
|
|
|
|
raise Exception("Socket certificate does not match (%s != %s)" % (cert_hash, cert_pin))
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
return sock_wrapped
|
2015-07-12 20:36:46 +02:00
|
|
|
else:
|
|
|
|
return sock
|
|
|
|
|
|
|
|
def removeCerts(self):
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
if config.keep_ssl_cert:
|
|
|
|
return False
|
2019-03-29 02:29:32 +01:00
|
|
|
for file_name in ["cert-rsa.pem", "key-rsa.pem", "cacert-rsa.pem", "cakey-rsa.pem", "cacert-rsa.srl", "cert-rsa.csr", "openssl-rand.tmp"]:
|
2015-07-12 20:36:46 +02:00
|
|
|
file_path = "%s/%s" % (config.data_dir, file_name)
|
|
|
|
if os.path.isfile(file_path):
|
|
|
|
os.unlink(file_path)
|
|
|
|
|
|
|
|
# Load and create cert files is necessary
|
|
|
|
def loadCerts(self):
|
|
|
|
if config.disable_encryption:
|
|
|
|
return False
|
|
|
|
|
2019-01-20 03:27:44 +01:00
|
|
|
if self.createSslRsaCert() and "tls-rsa" not in self.crypt_supported:
|
2015-07-12 20:36:46 +02:00
|
|
|
self.crypt_supported.append("tls-rsa")
|
|
|
|
|
|
|
|
# Try to create RSA server cert + sign for connection encryption
|
|
|
|
# Return: True on success
|
2015-09-24 22:08:08 +02:00
|
|
|
def createSslRsaCert(self):
|
2019-03-27 03:08:37 +01:00
|
|
|
casubjects = [
|
|
|
|
"/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon",
|
|
|
|
"/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3",
|
|
|
|
"/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA",
|
|
|
|
"/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA"
|
|
|
|
]
|
2019-08-15 03:08:40 +02:00
|
|
|
self.openssl_env['CN'] = random.choice(self.fakedomains)
|
2019-03-27 03:08:37 +01:00
|
|
|
|
|
|
|
if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem):
|
2019-08-15 03:08:40 +02:00
|
|
|
self.createSslContexts()
|
2015-07-12 20:36:46 +02:00
|
|
|
return True # Files already exits
|
|
|
|
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
import subprocess
|
2019-03-27 03:08:37 +01:00
|
|
|
|
2019-10-24 03:09:16 +02:00
|
|
|
# Replace variables in config template
|
|
|
|
conf_template = open(self.openssl_conf_template).read()
|
|
|
|
conf_template = conf_template.replace("$ENV::CN", self.openssl_env['CN'])
|
|
|
|
open(self.openssl_conf, "w").write(conf_template)
|
|
|
|
|
2019-03-27 03:08:37 +01:00
|
|
|
# Generate CAcert and CAkey
|
|
|
|
cmd_params = helper.shellquote(
|
|
|
|
self.openssl_bin,
|
2019-10-24 03:09:16 +02:00
|
|
|
self.openssl_conf,
|
2019-03-27 03:08:37 +01:00
|
|
|
random.choice(casubjects),
|
|
|
|
self.cakey_pem,
|
|
|
|
self.cacert_pem
|
|
|
|
)
|
|
|
|
cmd = "%s req -new -newkey rsa:2048 -days 3650 -nodes -x509 -config %s -subj %s -keyout %s -out %s -batch" % cmd_params
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.debug("Generating RSA CAcert and CAkey PEM files...")
|
|
|
|
self.log.debug("Running: %s" % cmd)
|
2019-03-27 03:08:37 +01:00
|
|
|
proc = subprocess.Popen(
|
|
|
|
cmd, shell=True, stderr=subprocess.STDOUT,
|
|
|
|
stdout=subprocess.PIPE, env=self.openssl_env
|
|
|
|
)
|
2019-09-03 12:00:25 +02:00
|
|
|
back = proc.stdout.read().strip().decode(errors="replace").replace("\r", "")
|
2019-03-27 03:08:37 +01:00
|
|
|
proc.wait()
|
|
|
|
|
|
|
|
if not (os.path.isfile(self.cacert_pem) and os.path.isfile(self.cakey_pem)):
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.error("RSA ECC SSL CAcert generation failed, CAcert or CAkey files not exist. (%s)" % back)
|
2019-03-27 03:08:37 +01:00
|
|
|
return False
|
2019-07-18 03:33:35 +02:00
|
|
|
else:
|
2019-09-03 12:00:25 +02:00
|
|
|
self.log.debug("Result: %s" % back)
|
2019-03-27 03:08:37 +01:00
|
|
|
|
|
|
|
# Generate certificate key and signing request
|
|
|
|
cmd_params = helper.shellquote(
|
|
|
|
self.openssl_bin,
|
|
|
|
self.key_pem,
|
|
|
|
self.cert_csr,
|
|
|
|
"/CN=" + self.openssl_env['CN'],
|
2019-10-24 03:09:16 +02:00
|
|
|
self.openssl_conf,
|
2019-03-27 03:08:37 +01:00
|
|
|
)
|
|
|
|
cmd = "%s req -new -newkey rsa:2048 -keyout %s -out %s -subj %s -sha256 -nodes -batch -config %s" % cmd_params
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.debug("Generating certificate key and signing request...")
|
2019-03-27 03:08:37 +01:00
|
|
|
proc = subprocess.Popen(
|
|
|
|
cmd, shell=True, stderr=subprocess.STDOUT,
|
|
|
|
stdout=subprocess.PIPE, env=self.openssl_env
|
|
|
|
)
|
2019-09-03 12:00:25 +02:00
|
|
|
back = proc.stdout.read().strip().decode(errors="replace").replace("\r", "")
|
2019-03-27 03:08:37 +01:00
|
|
|
proc.wait()
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.debug("Running: %s\n%s" % (cmd, back))
|
2019-03-27 03:08:37 +01:00
|
|
|
|
|
|
|
# Sign request and generate certificate
|
|
|
|
cmd_params = helper.shellquote(
|
2017-01-22 21:22:53 +01:00
|
|
|
self.openssl_bin,
|
2019-03-27 03:08:37 +01:00
|
|
|
self.cert_csr,
|
|
|
|
self.cacert_pem,
|
|
|
|
self.cakey_pem,
|
|
|
|
self.cert_pem,
|
2019-10-24 03:09:16 +02:00
|
|
|
self.openssl_conf
|
2017-01-22 21:22:53 +01:00
|
|
|
)
|
2019-04-10 19:59:02 +02:00
|
|
|
cmd = "%s x509 -req -in %s -CA %s -CAkey %s -set_serial 01 -out %s -days 730 -sha256 -extensions x509_ext -extfile %s" % cmd_params
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.debug("Generating RSA cert...")
|
2015-09-06 17:41:12 +02:00
|
|
|
proc = subprocess.Popen(
|
2019-03-16 02:37:38 +01:00
|
|
|
cmd, shell=True, stderr=subprocess.STDOUT,
|
|
|
|
stdout=subprocess.PIPE, env=self.openssl_env
|
2015-09-06 17:41:12 +02:00
|
|
|
)
|
2019-09-03 12:00:25 +02:00
|
|
|
back = proc.stdout.read().strip().decode(errors="replace").replace("\r", "")
|
2015-09-06 17:41:12 +02:00
|
|
|
proc.wait()
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.debug("Running: %s\n%s" % (cmd, back))
|
2015-07-12 20:36:46 +02:00
|
|
|
|
2019-03-27 03:08:37 +01:00
|
|
|
if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem):
|
2019-08-15 03:08:40 +02:00
|
|
|
self.createSslContexts()
|
2019-10-24 03:09:28 +02:00
|
|
|
|
|
|
|
# Remove no longer necessary files
|
|
|
|
os.unlink(self.openssl_conf)
|
|
|
|
os.unlink(self.cacert_pem)
|
|
|
|
os.unlink(self.cakey_pem)
|
|
|
|
os.unlink(self.cert_csr)
|
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
return True
|
|
|
|
else:
|
2019-07-18 03:33:35 +02:00
|
|
|
self.log.error("RSA ECC SSL cert generation failed, cert or key files not exist.")
|
2015-07-12 20:36:46 +02:00
|
|
|
|
2019-08-15 03:08:40 +02:00
|
|
|
|
2015-09-27 02:08:53 +02:00
|
|
|
manager = CryptConnectionManager()
|