added ability for concurrent sni challenges, made choc ext critical, allows variable oid

This commit is contained in:
James Kasten 2012-07-09 07:59:30 -04:00
parent ac3441a972
commit a3435b7982
2 changed files with 66 additions and 38 deletions

View file

@ -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()

View file

@ -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()