<commit_before>#!/usr/bin/env python

import subprocess
import M2Crypto
from Crypto import Random
import hmac
import hashlib
from shutil import move
from os import remove, close
import binascii
import augeas
import configurator
#import dns.resolver

#CHOC_DIR = "/home/ubuntu/chocolate/client-webserver/"
CHOC_DIR = "/home/james/Documents/apache_choc/"
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

def getChocCertFile(nonce):
    """
    Returns standardized name for challenge certificate

    nonce:  string - hex
    
    result: returns certificate file name
    """

    return CHOC_DIR + nonce + ".crt"

def findApacheConfigFile():
    """
    Locates the file path to the user's main apache config

    TODO: This needs to be rewritten... should use true ServerRoot
    
    result: returns file path if present
    """

    # This needs to be fixed to account for multiple httpd.conf files
    try:
        p = subprocess.check_output(["sudo", "find", "/etc", "-name", "httpd.conf"], stderr=open("/dev/null"))
	p = p[:len(p)-1]
	print "Apache Config: ", p
	return p
    except subprocess.CalledProcessError, e:
        print "httpd.conf not found"
	print "Please include .... in the conf file"
        return None

def getConfigText(nonce, ip_addr, key):
    """
    Chocolate virtual server configuration text

    nonce:      string - hex
    ip_addr:    string - address of challenged domain
    key:        string - file path to key

    result:     returns virtual host configuration text
    """

    configText = "<VirtualHost " + ip_addr + ":443> \n \
Servername " + nonce + ".chocolate \n \
UseCanonicalName on \n \
SSLStrictSNIVHostCheck on \n \
\n \
LimitRequestBody 1048576 \n \
\n \
Include " + OPTIONS_SSL_CONF + " \n \
SSLCertificateFile " + getChocCertFile(nonce) + " \n \
SSLCertificateKeyFile " + key + " \n \
\n \
DocumentRoot " + CHOC_DIR + "challenge_page/ \n \
</VirtualHost> \n\n "

    return configText

def modifyApacheConfig(mainConfig, listSNITuple, key, configurator):
    """
    Modifies Apache config files to include the challenge virtual servers
    
    mainConfig:    string - file path to Apache user config file
    listSNITuple:  list of tuples with form (addr, y, nonce, ext_oid)
                   addr (string), y (byte array), nonce (hex string), ext_oid (string)
    key:           string - file path to key

    result:        Apache config includes virtual servers for issued challenges
    """

    # TODO: Use ip address of existing vhost instead of relying on FQDN
    configText = "<IfModule mod_ssl.c> \n"
    for tup in listSNITuple:
        configText += getConfigText(tup[2], tup[0], key)
    configText += "</IfModule> \n"

    checkForApacheConfInclude(mainConfig, configurator)
    newConf = open(APACHE_CHALLENGE_CONF, 'w')
    newConf.write(configText)
    newConf.close()

# Need to add NameVirtualHost IP_ADDR or does the chocolate install do this?
def checkForApacheConfInclude(mainConfig, configurator):
    """
    Adds chocolate challenge include file if it does not already exist 
    within mainConfig
    
    mainConfig:  string - file path to main user apache config file

    result:      User Apache configuration includes chocolate sni challenge file
    """
    if len(configurator.find_directive("Include", APACHE_CHALLENGE_CONF)) == 0:
        configurator.add_dir("/files" + mainConfig, "Include", APACHE_CHALLENGE_CONF)
    #searchStr = "Include " + APACHE_CHALLENGE_CONF
    
    #conf = open(mainConfig, 'r+')
    #conf = open(mainConfig, 'r')
    #if not any(line.startswith(searchStr) for line in conf):
        #conf.write(searchStr)
	#process = subprocess.Popen(["echo", "\n" + searchStr], stdout=subprocess.PIPE)
        #subprocess.check_output(["sudo", "tee", "-a", mainConfig], stdin=process.stdout)
	#process.stdout.close()

    #conf.close()
        

def createChallengeCert(oid, ext, nonce, csr, key):
    """
    Modifies challenge certificate configuration and calls openssl binary to create a certificate

    oid:    string
    ext:    string - hex z value
    nonce:  string - hex
    csr:    string - file path to csr
    key:    string - file path to key

    result: certificate created at getChocCertFile(nonce)
    """

    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(key, y):
    """
    Generates z to be placed in certificate extension

    key:    string - File path to key
    y:      byte array
<commit_msg>Using Augeas to add Include directive for challenge vhosts<commit_after>#!/usr/bin/env python

import subprocess
import M2Crypto
from Crypto import Random
import hmac
import hashlib
from shutil import move
from os import remove, close
import binascii
import augeas
import configurator
#import dns.resolver

#CHOC_DIR = "/home/ubuntu/chocolate/client-webserver/"
CHOC_DIR = "/home/james/Documents/apache_choc/"
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

def getChocCertFile(nonce):
    """
    Returns standardized name for challenge certificate

    nonce:  string - hex
    
    result: returns certificate file name
    """

    return CHOC_DIR + nonce + ".crt"

def findApacheConfigFile():
    """
    Locates the file path to the user's main apache config

    TODO: This needs to be rewritten... should use true ServerRoot
    
    result: returns file path if present
    """

    # This needs to be fixed to account for multiple httpd.conf files
    try:
        p = subprocess.check_output(["sudo", "find", "/etc", "-name", "httpd.conf"], stderr=open("/dev/null"))
	p = p[:len(p)-1]
	print "Apache Config: ", p
	return p
    except subprocess.CalledProcessError, e:
        print "httpd.conf not found"
	print "Please include .... in the conf file"
        return None

def getConfigText(nonce, ip_addr, key):
    """
    Chocolate virtual server configuration text

    nonce:      string - hex
    ip_addr:    string - address of challenged domain
    key:        string - file path to key

    result:     returns virtual host configuration text
    """

    configText = "<VirtualHost " + ip_addr + ":443> \n \
Servername " + nonce + ".chocolate \n \
UseCanonicalName on \n \
SSLStrictSNIVHostCheck on \n \
\n \
LimitRequestBody 1048576 \n \
\n \
Include " + OPTIONS_SSL_CONF + " \n \
SSLCertificateFile " + getChocCertFile(nonce) + " \n \
SSLCertificateKeyFile " + key + " \n \
\n \
DocumentRoot " + CHOC_DIR + "challenge_page/ \n \
</VirtualHost> \n\n "

    return configText

def modifyApacheConfig(mainConfig, listSNITuple, key, configurator):
    """
    Modifies Apache config files to include the challenge virtual servers
    
    mainConfig:    string - file path to Apache user config file
    listSNITuple:  list of tuples with form (addr, y, nonce, ext_oid)
                   addr (string), y (byte array), nonce (hex string), ext_oid (string)
    key:           string - file path to key

    result:        Apache config includes virtual servers for issued challenges
    """

    # TODO: Use ip address of existing vhost instead of relying on FQDN
    configText = "<IfModule mod_ssl.c> \n"
    for tup in listSNITuple:
        configText += getConfigText(tup[2], tup[0], key)
    configText += "</IfModule> \n"

    checkForApacheConfInclude(mainConfig, configurator)
    newConf = open(APACHE_CHALLENGE_CONF, 'w')
    newConf.write(configText)
    newConf.close()

# Need to add NameVirtualHost IP_ADDR or does the chocolate install do this?
def checkForApacheConfInclude(mainConfig, configurator):
    """
    Adds chocolate challenge include file if it does not already exist 
    within mainConfig
    
    mainConfig:  string - file path to main user apache config file

    result:      User Apache configuration includes chocolate sni challenge file
    """
    if len(configurator.find_directive("Include", APACHE_CHALLENGE_CONF)) == 0:
        print "Including challenge server(s)"
        configurator.add_dir("/files" + mainConfig, "Include", APACHE_CHALLENGE_CONF)

def createChallengeCert(oid, ext, nonce, csr, key):
    """
    Modifies challenge certificate configuration and calls openssl binary to create a certificate

    oid:    string
    ext:    string - hex z value
    nonce:  string - hex
    csr:    string - file path to csr
    key:    string - file path to key

    result: certificate created at getChocCertFile(nonce)
    """

    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(key, y):
    """
    Generates z to be placed in certificate extension

    key:    string - File path to key
    y:      byte array

{'fraction_non_alphanumeric': 0.10008741258741259, 'fraction_numerical': 0.005463286713286713, 'mean_word_length': 3.1699316628701593, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6938925', 'n_tokens_mistral': 2937, 'n_tokens_neox': 2827, 'n_words': 913}