Randomize SSL subject (merged ValdikSS's commit)
This commit is contained in:
parent
cf354d59fb
commit
3d8d3a9237
2 changed files with 86 additions and 32 deletions
|
@ -3,6 +3,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import random
|
||||||
|
|
||||||
from Config import config
|
from Config import config
|
||||||
from util import helper
|
from util import helper
|
||||||
|
@ -12,13 +13,19 @@ class CryptConnectionManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# OpenSSL params
|
# OpenSSL params
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
self.openssl_bin = "src\\lib\\opensslVerify\\openssl.exe"
|
self.openssl_bin = "dist\\openssl\\openssl.exe"
|
||||||
else:
|
else:
|
||||||
self.openssl_bin = "openssl"
|
self.openssl_bin = "openssl"
|
||||||
self.openssl_env = {"OPENSSL_CONF": "src/lib/openssl/openssl.cnf"}
|
self.openssl_env = {"OPENSSL_CONF": "src/lib/openssl/openssl.cnf"}
|
||||||
|
|
||||||
self.crypt_supported = [] # Supported cryptos
|
self.crypt_supported = [] # Supported cryptos
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
# Select crypt that supported by both sides
|
# Select crypt that supported by both sides
|
||||||
# Return: Name of the crypto
|
# Return: Name of the crypto
|
||||||
def selectCrypt(self, client_supported):
|
def selectCrypt(self, client_supported):
|
||||||
|
@ -35,8 +42,9 @@ class CryptConnectionManager:
|
||||||
ciphers += "!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK"
|
ciphers += "!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK"
|
||||||
if server:
|
if server:
|
||||||
sock_wrapped = ssl.wrap_socket(
|
sock_wrapped = ssl.wrap_socket(
|
||||||
sock, server_side=server, keyfile='%s/key-rsa.pem' % config.data_dir,
|
sock, server_side=server, keyfile=self.key_pem,
|
||||||
certfile='%s/cert-rsa.pem' % config.data_dir, ciphers=ciphers)
|
certfile=self.cert_pem, ciphers=ciphers
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
sock_wrapped = ssl.wrap_socket(sock, ciphers=ciphers)
|
sock_wrapped = ssl.wrap_socket(sock, ciphers=ciphers)
|
||||||
if cert_pin:
|
if cert_pin:
|
||||||
|
@ -49,7 +57,7 @@ class CryptConnectionManager:
|
||||||
def removeCerts(self):
|
def removeCerts(self):
|
||||||
if config.keep_ssl_cert:
|
if config.keep_ssl_cert:
|
||||||
return False
|
return False
|
||||||
for file_name in ["cert-rsa.pem", "key-rsa.pem"]:
|
for file_name in ["cert-rsa.pem", "key-rsa.pem", "cacert-rsa.pem", "cakey-rsa.pem", "cacert-rsa.srl", "cert-rsa.csr"]:
|
||||||
file_path = "%s/%s" % (config.data_dir, file_name)
|
file_path = "%s/%s" % (config.data_dir, file_name)
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
os.unlink(file_path)
|
os.unlink(file_path)
|
||||||
|
@ -65,28 +73,86 @@ class CryptConnectionManager:
|
||||||
# Try to create RSA server cert + sign for connection encryption
|
# Try to create RSA server cert + sign for connection encryption
|
||||||
# Return: True on success
|
# Return: True on success
|
||||||
def createSslRsaCert(self):
|
def createSslRsaCert(self):
|
||||||
if os.path.isfile("%s/cert-rsa.pem" % config.data_dir) and os.path.isfile("%s/key-rsa.pem" % config.data_dir):
|
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"
|
||||||
|
]
|
||||||
|
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"
|
||||||
|
]
|
||||||
|
self.openssl_env['CN'] = random.choice(fakedomains)
|
||||||
|
|
||||||
|
if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem):
|
||||||
return True # Files already exits
|
return True # Files already exits
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
cmd = "%s req -x509 -newkey rsa:2048 -sha256 -batch -keyout %s -out %s -nodes -config %s" % helper.shellquote(
|
|
||||||
|
# Generate CAcert and CAkey
|
||||||
|
cmd_params = helper.shellquote(
|
||||||
self.openssl_bin,
|
self.openssl_bin,
|
||||||
config.data_dir + "/key-rsa.pem",
|
self.openssl_env["OPENSSL_CONF"],
|
||||||
config.data_dir + "/cert-rsa.pem",
|
random.choice(casubjects),
|
||||||
self.openssl_env["OPENSSL_CONF"]
|
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
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
cmd, shell=True, stderr=subprocess.STDOUT,
|
cmd, shell=True, stderr=subprocess.STDOUT,
|
||||||
stdout=subprocess.PIPE, env=self.openssl_env
|
stdout=subprocess.PIPE, env=self.openssl_env
|
||||||
)
|
)
|
||||||
back = proc.stdout.read().strip()
|
back = proc.stdout.read().strip()
|
||||||
proc.wait()
|
proc.wait()
|
||||||
logging.debug("Generating RSA cert and key PEM files...%s" % back)
|
logging.debug("Generating RSA CAcert and CAkey PEM files... %s: %s" % (cmd, back.decode()))
|
||||||
|
|
||||||
if os.path.isfile("%s/cert-rsa.pem" % config.data_dir) and os.path.isfile("%s/key-rsa.pem" % config.data_dir):
|
if not (os.path.isfile(self.cacert_pem) and os.path.isfile(self.cakey_pem)):
|
||||||
return True
|
logging.error("RSA ECC SSL CAcert generation failed, CAcert or CAkey files not exist.")
|
||||||
else:
|
|
||||||
logging.error("RSA SSL cert generation failed, cert or key files not exist.")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Generate certificate key and signing request
|
||||||
|
cmd_params = helper.shellquote(
|
||||||
|
self.openssl_bin,
|
||||||
|
self.key_pem,
|
||||||
|
self.cert_csr,
|
||||||
|
"/CN=" + self.openssl_env['CN'],
|
||||||
|
self.openssl_env["OPENSSL_CONF"],
|
||||||
|
)
|
||||||
|
cmd = "%s req -new -newkey rsa:2048 -keyout %s -out %s -subj %s -sha256 -nodes -batch -config %s" % cmd_params
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
cmd, shell=True, stderr=subprocess.STDOUT,
|
||||||
|
stdout=subprocess.PIPE, env=self.openssl_env
|
||||||
|
)
|
||||||
|
back = proc.stdout.read().strip()
|
||||||
|
proc.wait()
|
||||||
|
logging.debug("Generating certificate key and signing request...%s" % back.decode())
|
||||||
|
|
||||||
|
# Sign request and generate certificate
|
||||||
|
cmd_params = helper.shellquote(
|
||||||
|
self.openssl_bin,
|
||||||
|
self.cert_csr,
|
||||||
|
self.cacert_pem,
|
||||||
|
self.cakey_pem,
|
||||||
|
self.cert_pem,
|
||||||
|
self.openssl_env["OPENSSL_CONF"]
|
||||||
|
)
|
||||||
|
cmd = "%s x509 -req -in %s -CA %s -CAkey %s -CAcreateserial -out %s -days 730 -sha256 -extensions x509_ext -extfile %s" % cmd_params
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
cmd, shell=True, stderr=subprocess.STDOUT,
|
||||||
|
stdout=subprocess.PIPE, env=self.openssl_env
|
||||||
|
)
|
||||||
|
back = proc.stdout.read().strip()
|
||||||
|
proc.wait()
|
||||||
|
logging.debug("Generating RSA cert...%s" % back.decode())
|
||||||
|
|
||||||
|
if os.path.isfile(self.cert_pem) and os.path.isfile(self.key_pem):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error("RSA ECC SSL cert generation failed, cert or key files not exist.")
|
||||||
|
|
||||||
manager = CryptConnectionManager()
|
manager = CryptConnectionManager()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[ req ]
|
[ req ]
|
||||||
prompt = no
|
default_bits = 2048
|
||||||
default_bits = 1024
|
|
||||||
default_keyfile = server-key.pem
|
default_keyfile = server-key.pem
|
||||||
distinguished_name = subject
|
distinguished_name = subject
|
||||||
req_extensions = req_ext
|
req_extensions = req_ext
|
||||||
|
@ -13,7 +12,7 @@ string_mask = utf8only
|
||||||
countryName = US
|
countryName = US
|
||||||
stateOrProvinceName = NY
|
stateOrProvinceName = NY
|
||||||
localityName = New York
|
localityName = New York
|
||||||
organizationName = Example Company, LLC
|
organizationName = Example, LLC
|
||||||
|
|
||||||
# Use a friendly name here because its presented to the user. The server's DNS
|
# Use a friendly name here because its presented to the user. The server's DNS
|
||||||
# names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
|
# names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
|
||||||
|
@ -32,8 +31,8 @@ authorityKeyIdentifier = keyid,issuer
|
||||||
|
|
||||||
basicConstraints = CA:FALSE
|
basicConstraints = CA:FALSE
|
||||||
keyUsage = digitalSignature, keyEncipherment
|
keyUsage = digitalSignature, keyEncipherment
|
||||||
|
extendedKeyUsage = clientAuth, serverAuth
|
||||||
subjectAltName = @alternate_names
|
subjectAltName = @alternate_names
|
||||||
nsComment = "OpenSSL Generated Certificate"
|
|
||||||
|
|
||||||
# RFC 5280, Section 4.2.1.12 makes EKU optional
|
# RFC 5280, Section 4.2.1.12 makes EKU optional
|
||||||
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
|
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
|
||||||
|
@ -46,8 +45,8 @@ subjectKeyIdentifier = hash
|
||||||
|
|
||||||
basicConstraints = CA:FALSE
|
basicConstraints = CA:FALSE
|
||||||
keyUsage = digitalSignature, keyEncipherment
|
keyUsage = digitalSignature, keyEncipherment
|
||||||
|
extendedKeyUsage = clientAuth, serverAuth
|
||||||
subjectAltName = @alternate_names
|
subjectAltName = @alternate_names
|
||||||
nsComment = "OpenSSL Generated Certificate"
|
|
||||||
|
|
||||||
# RFC 5280, Section 4.2.1.12 makes EKU optional
|
# RFC 5280, Section 4.2.1.12 makes EKU optional
|
||||||
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
|
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
|
||||||
|
@ -55,16 +54,5 @@ nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
[ alternate_names ]
|
[ alternate_names ]
|
||||||
|
|
||||||
DNS.1 = example.company.com
|
DNS.1 = $ENV::CN
|
||||||
DNS.2 = www.example.company.com
|
DNS.2 = www.$ENV::CN
|
||||||
DNS.3 = mail.example.company.com
|
|
||||||
DNS.4 = ftp.example.company.com
|
|
||||||
|
|
||||||
# Add these if you need them. But usually you don't want them or
|
|
||||||
# need them in production. You may need them for development.
|
|
||||||
# DNS.5 = localhost
|
|
||||||
# DNS.6 = localhost.localdomain
|
|
||||||
# DNS.7 = 127.0.0.1
|
|
||||||
|
|
||||||
# IPv6 localhost
|
|
||||||
# DNS.8 = ::1
|
|
Loading…
Reference in a new issue