mirror of
https://github.com/certbot/certbot.git
synced 2026-06-03 13:59:02 -04:00
added ability for concurrent sni challenges, made choc ext critical, allows variable oid
This commit is contained in:
parent
ac3441a972
commit
a3435b7982
2 changed files with 66 additions and 38 deletions
|
|
@ -9,17 +9,19 @@ from shutil import move
|
|||
from os import remove, close
|
||||
|
||||
CHOC_DIR = "/home/james/Documents/apache_choc/"
|
||||
#CHOC_KEY = "../ca/sni_challenge/testing.key"
|
||||
CHOC_KEY = CHOC_DIR + "testing.key"
|
||||
SERVER_BASE = "/etc/apache2/"
|
||||
CHOC_CERT = CHOC_DIR + "choc.crt"
|
||||
CSR = CHOC_DIR + "choc.csr"
|
||||
CHOC_CERT_CONF = "choc_cert_extensions.cnf"
|
||||
OPTIONS_SSL_CONF = CHOC_DIR + "options-ssl.conf"
|
||||
APACHE_CHALLENGE_CONF = CHOC_DIR + "choc_sni_cert_challenge.conf"
|
||||
S_SIZE = 32
|
||||
NONCE_SIZE = 32
|
||||
|
||||
#class sni_challenge(object):
|
||||
# def __init__(self, ip_addrs, y, nonce):
|
||||
# self.address = ip_addrs
|
||||
|
||||
def getChocCertFile(nonce):
|
||||
return CHOC_DIR + byteToHex(nonce) + ".crt"
|
||||
|
||||
def findApacheConfigFile():
|
||||
#This needs to be fixed to account for multiple httpd.conf files
|
||||
try:
|
||||
|
|
@ -32,7 +34,7 @@ def findApacheConfigFile():
|
|||
print "Please include .... in the conf file"
|
||||
return None
|
||||
|
||||
def modifyApacheConfig(mainConfig, nonce, ip_addr):
|
||||
def getConfigText(nonce, ip_addr, key):
|
||||
configText = "<IfModule mod_ssl.c> \n \
|
||||
<VirtualHost " + ip_addr + ":443> \n \
|
||||
Servername " + nonce + ".chocolate \n \
|
||||
|
|
@ -41,19 +43,26 @@ UseCanonicalName on \n \
|
|||
LimitRequestBody 1048576 \n \
|
||||
\n \
|
||||
Include " + OPTIONS_SSL_CONF + " \n \
|
||||
SSLCertificateFile " + CHOC_CERT + " \n \
|
||||
SSLCertificateKeyFile " + CHOC_KEY + " \n \
|
||||
SSLCertificateFile " + getChocCertFile(nonce) + " \n \
|
||||
SSLCertificateKeyFile " + key + " \n \
|
||||
\n \
|
||||
DocumentRoot " + CHOC_DIR + "challenge_page/ \n \
|
||||
</VirtualHost> \n \
|
||||
</IfModule>"
|
||||
</IfModule> \n"
|
||||
|
||||
return configText
|
||||
|
||||
def modifyApacheConfig(mainConfig, listSNITuple):
|
||||
configText = ""
|
||||
for tup in listSNITuple:
|
||||
configText += getConfigText(tup[2], tup[0], tup[5])
|
||||
|
||||
checkForApacheConfInclude(mainConfig)
|
||||
newConf = open(APACHE_CHALLENGE_CONF, 'w')
|
||||
newConf.write(configText)
|
||||
newConf.close()
|
||||
|
||||
# Need to add NameVirtualHost IP_ADDR
|
||||
# Need to add NameVirtualHost IP_ADDR or does the chocolate install do this?
|
||||
def checkForApacheConfInclude(mainConfig):
|
||||
searchStr = "Include " + APACHE_CHALLENGE_CONF
|
||||
#conf = open(mainConfig, 'r+')
|
||||
|
|
@ -64,19 +73,19 @@ def checkForApacheConfInclude(mainConfig):
|
|||
subprocess.check_output(["sudo", "tee", "-a", mainConfig], stdin=process.stdout)
|
||||
process.stdout.close()
|
||||
|
||||
conf.close();
|
||||
conf.close()
|
||||
|
||||
|
||||
def createChallengeCert(ext):
|
||||
def createChallengeCert(oid, ext, nonce, csr, key):
|
||||
#Assume CSR is already generated from original request
|
||||
updateCertConf(ext)
|
||||
subprocess.call(["openssl", "x509", "-req", "-days", "21", "-extfile", CHOC_CERT_CONF, "-extensions", "v3_ca", "-signkey", CHOC_KEY, "-out", CHOC_CERT, "-in", CSR])
|
||||
updateCertConf(oid, ext)
|
||||
subprocess.call(["openssl", "x509", "-req", "-days", "21", "-extfile", CHOC_CERT_CONF, "-extensions", "v3_ca", "-signkey", key, "-out", getChocCertFile(nonce), "-in", csr])
|
||||
|
||||
|
||||
def generateExtension(challengeValue):
|
||||
rsaPrivKey = RSA.importKey(open(CHOC_KEY).read())
|
||||
r = rsaPrivKey.decrypt(challengeValue)
|
||||
print r
|
||||
def generateExtension(key, y):
|
||||
rsaPrivKey = RSA.importKey(open(key).read())
|
||||
r = rsaPrivKey.decrypt(y)
|
||||
#print r
|
||||
|
||||
s = Random.get_random_bytes(S_SIZE)
|
||||
#s = "0xDEADBEEF"
|
||||
|
|
@ -86,13 +95,22 @@ def generateExtension(challengeValue):
|
|||
def byteToHex(byteStr):
|
||||
return ''.join(["%02X" % ord(x) for x in byteStr]).strip()
|
||||
|
||||
def updateCertConf(value):
|
||||
#Searches for the first extension specified in binary
|
||||
def updateCertConf(oid, value):
|
||||
"""
|
||||
Updates the sni_challenge openssl certificate config file
|
||||
|
||||
oid: string - ex. 1.3.3.7
|
||||
value string hex - value of OID
|
||||
|
||||
result: updated certificate config file
|
||||
"""
|
||||
confOld = open(CHOC_CERT_CONF)
|
||||
confNew = open(CHOC_CERT_CONF + ".tmp", 'w')
|
||||
|
||||
for line in confOld:
|
||||
if line.startswith("1.3.3.7=DER:"):
|
||||
confNew.write("1.3.3.7=DER:" + value + "\n")
|
||||
if "=critical, DER:" in line:
|
||||
confNew.write(oid + "=critical, DER:" + value + "\n")
|
||||
else:
|
||||
confNew.write(line)
|
||||
confNew.close()
|
||||
|
|
@ -104,28 +122,37 @@ def apache_restart():
|
|||
subprocess.call(["sudo", "/etc/init.d/apache2", "reload"])
|
||||
|
||||
#main call
|
||||
def perform_sni_cert_challenge(address, r, nonce):
|
||||
ext = generateExtension(r)
|
||||
createChallengeCert(ext)
|
||||
# address, y, nonce, ext, CSR, KEY
|
||||
def perform_sni_cert_challenge(listSNITuple):
|
||||
for tup in listSNITuple:
|
||||
ext = generateExtension(tup[5], tup[1])
|
||||
createChallengeCert(tup[3], ext, tup[2], tup[4], tup[5])
|
||||
|
||||
#Need to decide the form of nonce
|
||||
modifyApacheConfig(findApacheConfigFile(), nonce, address)
|
||||
modifyApacheConfig(findApacheConfigFile(), listSNITuple)
|
||||
apache_restart()
|
||||
|
||||
def main():
|
||||
key = CHOC_DIR + "testing.key"
|
||||
key2 = CHOC_DIR + "testing2.key"
|
||||
csr = CHOC_DIR + "choc.csr"
|
||||
csr2 = CHOC_DIR + "choc2.csr"
|
||||
|
||||
testkey = RSA.importKey(open(CHOC_KEY).read())
|
||||
|
||||
#the second parameter is ignored
|
||||
#https://www.dlitz.net/software/pycrypto/api/current/
|
||||
testkey = RSA.importKey(open(key).read())
|
||||
testkey2 = RSA.importKey(open(key2).read())
|
||||
|
||||
r = Random.get_random_bytes(S_SIZE)
|
||||
r = "testValueForR"
|
||||
nonce = Random.get_random_bytes(NONCE_SIZE)
|
||||
nonce = "nonce"
|
||||
r2 = "testValueForR2"
|
||||
nonce2 = "nonce2"
|
||||
|
||||
#the second parameter is ignored
|
||||
#https://www.dlitz.net/software/pycrypto/api/current/
|
||||
y = testkey.encrypt(r, 0)
|
||||
perform_sni_cert_challenge("127.0.0.1", y, nonce)
|
||||
y2 = testkey2.encrypt(r2, 0)
|
||||
|
||||
perform_sni_cert_challenge([("127.0.0.1", y, nonce, "1.3.3.7", csr, key), ("localhost",y2, nonce2, "1.3.3.7", csr2, key2)])
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -84,15 +84,16 @@ def main():
|
|||
|
||||
nonce = Random.get_random_bytes(NONCE_SIZE)
|
||||
nonce = "nonce"
|
||||
testkey = RSA.importKey(open("testing.key").read())
|
||||
|
||||
#the second parameter is ignored
|
||||
#https://www.dlitz.net/software/pycrypto/api/current/
|
||||
nonce2 = "nonce2"
|
||||
|
||||
r = Random.get_random_bytes(NONCE_SIZE)
|
||||
r = "testValueForR"
|
||||
encryptedValue = testkey.encrypt(r, 0)
|
||||
valid, response = verify_challenge("127.0.0.1", r, binascii.hexlify(nonce))
|
||||
print response
|
||||
r2 = "testValueForR2"
|
||||
|
||||
#valid, response = verify_challenge("127.0.0.1", r, binascii.hexlify(nonce))
|
||||
valid, response = verify_challenge("127.0.0.1", r, nonce)
|
||||
print response
|
||||
valid, response = verify_challenge("localhost", r2, nonce2)
|
||||
print response
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in a new issue