diff --git a/client-webserver/sni_challenge.py b/client-webserver/sni_challenge.py index 1b2666d76..ac0dc1162 100644 --- a/client-webserver/sni_challenge.py +++ b/client-webserver/sni_challenge.py @@ -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 = " \n \ \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 \ \n \ -" + \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() diff --git a/server-ca/sni_challenge/verify_sni_challenge.py b/server-ca/sni_challenge/verify_sni_challenge.py index ced6f388f..7c48c74ce 100644 --- a/server-ca/sni_challenge/verify_sni_challenge.py +++ b/server-ca/sni_challenge/verify_sni_challenge.py @@ -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()