Final touches before case insensitive Augeas testing begins

This commit is contained in:
James Kasten 2013-05-19 14:12:33 -04:00
parent e75489b2df
commit 9bd7b4ff7b
3 changed files with 177 additions and 167 deletions

View file

@ -14,7 +14,7 @@ def main():
sys.exit("\nOnly root can run trustify.\n")
# Parse options
try:
opts, args = getopt.getopt(sys.argv[1:], "", ["text", "view-checkpoints", "privkey=", "csr=", "server=", "rollback="])
opts, args = getopt.getopt(sys.argv[1:], "", ["text", "test", "view-checkpoints", "privkey=", "csr=", "server=", "rollback="])
except getopt.GetoptError as err:
# print help info and exit
print str(err)
@ -46,7 +46,10 @@ def main():
config = configurator.Configurator()
config.display_checkpoints()
sys.exit(0)
elif o == "--test":
#put any temporary tests in here
continue
if not server:
if "CHOCOLATESERVER" in os.environ:
server = os.environ["CHOCOLATESERVER"]

View file

@ -28,7 +28,6 @@ from trustify.client.CONFIG import SERVER_ROOT, KEY_DIR, CERT_DIR
allow_raw_ipv6_server = False
RSA_KEY_SIZE = 2048
class Client(object):
# In case of import, dialog needs scope over the class
dialog = None
@ -566,34 +565,34 @@ def sha256(m):
# return result[1] == "Secure"
def rsa_sign(key, data):
"""
Sign this data with this private key. For client-side use.
# def rsa_sign(key, data):
# """
# Sign this data with this private key. For client-side use.
@type key: str
@param key: PEM-encoded string of the private key.
# @type key: str
# @param key: PEM-encoded string of the private key.
@type data: str
@param data: The data to be signed. Will be hashed (sha256) prior to
signing.
# @type data: str
# @param data: The data to be signed. Will be hashed (sha256) prior to
# signing.
@return: binary string of the signature
"""
key = str(key)
data = str(data)
privkey = M2Crypto.RSA.load_key_string(key)
return privkey.sign(hashlib.sha256(data).digest(), 'sha256')
# @return: binary string of the signature
# """
# key = str(key)
# data = str(data)
# privkey = M2Crypto.RSA.load_key_string(key)
# return privkey.sign(hashlib.sha256(data).digest(), 'sha256')
def do(upstream, m):
u = urllib2.urlopen(upstream, m.SerializeToString())
return u.read()
# def do(upstream, m):
# u = urllib2.urlopen(upstream, m.SerializeToString())
# return u.read()
def decode(m):
return (chocolatemessage.FromString(m))
# def decode(m):
# return (chocolatemessage.FromString(m))
def init(m):
m.chocolateversion = 1
m.session = ""
# def init(m):
# m.chocolateversion = 1
# m.session = ""
def drop_privs():
nogroup = grp.getgrnam("nogroup").gr_gid
@ -614,8 +613,8 @@ def drop_privs():
# if hashcash: m.request.clientpuzzle = hashcash
def sign(key, m):
m.request.sig = rsa_sign(key, ("(%d) (%s) (%s)" % (m.request.timestamp, m.request.recipient, m.request.csr)))
# def sign(key, m):
# m.request.sig = rsa_sign(key, ("(%d) (%s) (%s)" % (m.request.timestamp, m.request.recipient, m.request.csr)))
def old_cert(cert_filename, days_left):
cert = M2Crypto.X509.load_cert(cert_filename)
@ -841,154 +840,154 @@ def renew(config):
# return True
def authenticate():
"""
Main call to do DV_SNI validation and deploy the trustify certificate
TODO: This should be turned into a class...
"""
global server, names, csr, privkey
# def authenticate():
# """
# Main call to do DV_SNI validation and deploy the trustify certificate
# TODO: This should be turned into a class...
# """
# global server, names, csr, privkey
# Check if root
if not os.geteuid()==0:
sys.exit("\nOnly root can run trustify\n")
# # Check if root
# if not os.geteuid()==0:
# sys.exit("\nOnly root can run trustify\n")
if "CHOCOLATESERVER" in os.environ:
server = os.environ["CHOCOLATESERVER"]
if not server:
# Global default value for Chocolate server!
server = "ca.theobroma.info"
# if "CHOCOLATESERVER" in os.environ:
# server = os.environ["CHOCOLATESERVER"]
# if not server:
# # Global default value for Chocolate server!
# server = "ca.theobroma.info"
assert is_hostname_sane(server), `server` + " is an impossible hostname"
# assert is_hostname_sane(server), `server` + " is an impossible hostname"
upstream = "https://%s/chocolate.py" % server
# upstream = "https://%s/chocolate.py" % server
if curses:
logger.setLogger(logger.NcursesLogger())
logger.setLogLevel(logger.INFO)
else:
logger.setLogger(sys.stdout)
logger.setLogLevel(logger.INFO)
# if curses:
# logger.setLogger(logger.NcursesLogger())
# logger.setLogLevel(logger.INFO)
# else:
# logger.setLogger(sys.stdout)
# logger.setLogLevel(logger.INFO)
# Logger should be init before config
config = configurator.Configurator()
# # Logger should be init before config
# config = configurator.Configurator()
if not names:
names = config.get_all_names()
# if not names:
# names = config.get_all_names()
if curses:
if not names:
logger.fatal("No domain names were found in your apache config")
logger.fatal("Either specify which names you would like trustify to validate or add server names to your virtual hosts")
sys.exit(1)
# if curses:
# if not names:
# logger.fatal("No domain names were found in your apache config")
# logger.fatal("Either specify which names you would like trustify to validate or add server names to your virtual hosts")
# sys.exit(1)
names = filter_names(names)
choice = choice_of_ca()
if choice[0] != 0:
sys.exit(1)
# names = filter_names(names)
# choice = choice_of_ca()
# if choice[0] != 0:
# sys.exit(1)
# Check first if mod_ssl is loaded
if not config.check_ssl_loaded():
logger.info("Loading mod_ssl into Apache Server")
config.enable_mod("ssl")
# # Check first if mod_ssl is loaded
# if not config.check_ssl_loaded():
# logger.info("Loading mod_ssl into Apache Server")
# config.enable_mod("ssl")
req_file = csr
key_file = privkey
if csr and privkey:
csr_pem = open(req_file).read().replace("\r", "")
key_pem = open(key_file).read().replace("\r", "")
if not csr or not privkey:
# Generate new private key and corresponding csr!
key_pem, csr_pem = make_key_and_csr(names, 2048)
key_file, req_file = save_key_csr(key_pem, csr_pem)
logger.info("Generating key: " + key_file)
logger.info("Creating CSR: " + req_file)
# req_file = csr
# key_file = privkey
# if csr and privkey:
# csr_pem = open(req_file).read().replace("\r", "")
# key_pem = open(key_file).read().replace("\r", "")
# if not csr or not privkey:
# # Generate new private key and corresponding csr!
# key_pem, csr_pem = make_key_and_csr(names, 2048)
# key_file, req_file = save_key_csr(key_pem, csr_pem)
# logger.info("Generating key: " + key_file)
# logger.info("Creating CSR: " + req_file)
r, k = send_request(key_pem, csr_pem, names)
# r, k = send_request(key_pem, csr_pem, names)
challenges, dn = challenge_factory(r, os.path.abspath(req_file), os.path.abspath(key_file), config)
# challenges, dn = challenge_factory(r, os.path.abspath(req_file), os.path.abspath(key_file), config)
# Find set of virtual hosts to deploy certificates to
vhost = set()
for name in dn:
host = config.choose_virtual_host(name)
if host is not None:
vhost.add(host)
# # Find set of virtual hosts to deploy certificates to
# vhost = set()
# for name in dn:
# host = config.choose_virtual_host(name)
# if host is not None:
# vhost.add(host)
for challenge in challenges:
if not challenge.perform(quiet=curses):
# TODO: In this case the client should probably send a failure
# to the server.
logger.fatal("challenge failed")
sys.exit(1)
logger.info("Configured Apache for challenge; waiting for verification...")
# for challenge in challenges:
# if not challenge.perform(quiet=curses):
# # TODO: In this case the client should probably send a failure
# # to the server.
# logger.fatal("challenge failed")
# sys.exit(1)
# logger.info("Configured Apache for challenge; waiting for verification...")
#############################################################
# This whole bottom section should be reworked once the protocol
# is finalized... it is currently quite ugly
############################################################
# #############################################################
# # This whole bottom section should be reworked once the protocol
# # is finalized... it is currently quite ugly
# ############################################################
did_it = chocolatemessage()
init(did_it)
did_it.session = r.session
# This will blindly assert that all of the challenges have been
# complied with, by simply copying them from the challenge data
# structure into a new completedchallenge structure. This is
# kind of crude, because the client could instead actually build up
# a completedchallenge structure piece-by-piece as it actually
# complies with challenges (and then send that structure for the
# server to look at). In the existing client, completedchallenge
# is only ever sent once _all_ of the (assumed to be dvsni)
# challenges have been met, and client-side failure to meet any
# challenge is immediately fatal to the client. In the existing
# server, the client's assertion that the client has met any
# (assumed to be dvsni) challenge(s) will result in the server
# scheduling a test of all challenges.
did_it.completedchallenge.extend(r.challenge)
# did_it = chocolatemessage()
# init(did_it)
# did_it.session = r.session
# # This will blindly assert that all of the challenges have been
# # complied with, by simply copying them from the challenge data
# # structure into a new completedchallenge structure. This is
# # kind of crude, because the client could instead actually build up
# # a completedchallenge structure piece-by-piece as it actually
# # complies with challenges (and then send that structure for the
# # server to look at). In the existing client, completedchallenge
# # is only ever sent once _all_ of the (assumed to be dvsni)
# # challenges have been met, and client-side failure to meet any
# # challenge is immediately fatal to the client. In the existing
# # server, the client's assertion that the client has met any
# # (assumed to be dvsni) challenge(s) will result in the server
# # scheduling a test of all challenges.
# did_it.completedchallenge.extend(r.challenge)
r=decode(do(upstream, did_it))
logger.debug(r)
delay = 5
#while r.challenge or r.proceed.IsInitialized():
while r.proceed.IsInitialized() or (r.challenge and not all_payment_challenge(r)):
if r.proceed.IsInitialized():
delay = min(r.proceed.polldelay, 60)
logger.debug("waiting %d" % delay)
time.sleep(delay)
k.session = r.session
r = decode(do(upstream, k))
logger.debug(r)
# r=decode(do(upstream, did_it))
# logger.debug(r)
# delay = 5
# #while r.challenge or r.proceed.IsInitialized():
# while r.proceed.IsInitialized() or (r.challenge and not all_payment_challenge(r)):
# if r.proceed.IsInitialized():
# delay = min(r.proceed.polldelay, 60)
# logger.debug("waiting %d" % delay)
# time.sleep(delay)
# k.session = r.session
# r = decode(do(upstream, k))
# logger.debug(r)
# This should be invoked if a payment is necessary
# This is being tested and will have to be cleaned and organized
# once the protocol is finalized.
while r.challenge and all_payment_challenge(r):
# dont need to change domain names here
paymentChallenges, temp = challenge_factory(r, os.path.abspath(req_file), os.path.abspath(key_file), config)
for chall in paymentChallenges:
chall.perform(quiet=curses)
# # This should be invoked if a payment is necessary
# # This is being tested and will have to be cleaned and organized
# # once the protocol is finalized.
# while r.challenge and all_payment_challenge(r):
# # dont need to change domain names here
# paymentChallenges, temp = challenge_factory(r, os.path.abspath(req_file), os.path.abspath(key_file), config)
# for chall in paymentChallenges:
# chall.perform(quiet=curses)
logger.info("User has continued Trustify after submitting payment")
proceed_msg = chocolatemessage()
init(proceed_msg)
proceed_msg.session = r.session
proceed_msg.proceed.timestamp = int(time.time())
proceed_msg.proceed.polldelay = 60
# Send the proceed message
r = decode(do(upstream, k))
# logger.info("User has continued Trustify after submitting payment")
# proceed_msg = chocolatemessage()
# init(proceed_msg)
# proceed_msg.session = r.session
# proceed_msg.proceed.timestamp = int(time.time())
# proceed_msg.proceed.polldelay = 60
# # Send the proceed message
# r = decode(do(upstream, k))
while r.proceed.IsInitialized():
if r.proceed.IsInitialized():
delay = min(r.proceed.polldelay, 60)
logger.debug("waiting %d" % delay)
time.sleep(delay)
k.session = r.session
r = decode(do(upstream, k))
logger.debug(r)
# while r.proceed.IsInitialized():
# if r.proceed.IsInitialized():
# delay = min(r.proceed.polldelay, 60)
# logger.debug("waiting %d" % delay)
# time.sleep(delay)
# k.session = r.session
# r = decode(do(upstream, k))
# logger.debug(r)
handle_verification_response(r, dn, challenges, vhost, key_file, config)
# handle_verification_response(r, dn, challenges, vhost, key_file, config)
# vim: set expandtab tabstop=4 shiftwidth=4

View file

@ -17,6 +17,10 @@ from trustify.client import logger
# Question: Am I missing any attacks that can result from modifying CONFIG file?
# Configurator should be turned into a Singleton
# Note: Apache 2.4 NameVirtualHost directive is deprecated... all vhost twins
# are considered name based vhosts by default. The use of the directive will
# emit a warning.
class VH(object):
def __init__(self, filename_path, vh_path, vh_addrs, is_ssl, is_enabled):
self.file = filename_path
@ -238,21 +242,22 @@ class Configurator(object):
for p in paths:
name_vh.append(self.aug.get(p))
# TODO: Reread NameBasedVirtual host matching... I think it must be an
# exact match
# Mixed and matched wildcard NameVirtualHost with VirtualHost
# behavior is undefined. Make sure that an exact match exists
# Check for exact match
for vh in name_vh:
if vh == addr:
return True
# Check for general IP_ADDR name_vh
tup = addr.partition(":")
for vh in name_vh:
if vh == tup[0]:
return True
# Check for straight wildcard name_vh
for vh in name_vh:
if vh == "*":
return True
# # Check for general IP_ADDR name_vh
# tup = addr.partition(":")
# for vh in name_vh:
# if vh == tup[0]:
# return True
# # Check for straight wildcard name_vh
# for vh in name_vh:
# if vh == "*":
# return True
# NameVirtualHost directive should be added for this address
return False
@ -498,12 +503,15 @@ class Configurator(object):
# The configuration must also be saved before being searched
# for the new directives; For these reasons... this is tacked
# on after fully creating the new vhost
# TODO: Figure out what to do for vhosts with multiple addresses
if len(nonssl_vhost.addrs) == 1:
if self.is_name_vhost(nonssl_vhost.addrs[0]) and not self.is_name_vhost(ssl_addrs[0]):
self.add_name_vhost(ssl_addrs[0])
logger.info("Enabling NameVirtualHosts on " + ssl_addrs[0])
self.save("Added permanent NameVirtualHost for " + ssl_addrs[0])
need_to_save = False
for i in range(len(nonssl_vhost.addrs)):
if self.is_name_vhost(nonssl_vhost.addrs[i]) and not self.is_name_vhost(ssl_addrs[i]):
self.add_name_vhost(ssl_addrs[i])
logger.info("Enabling NameVirtualHosts on " + ssl_addrs[i])
need_to_save = True
if need_to_save:
self.save("Added permanent NameVirtualHost for " + ssl_addrs[i])
return ssl_vhost