Added interactive challenge client-side code

This commit is contained in:
James Kasten 2012-11-14 17:52:08 -05:00
parent dc1f0bef16
commit ea994a4052
3 changed files with 72 additions and 27 deletions

View file

@ -60,9 +60,9 @@ def choice_of_ca():
# XXX This is a stub
d = dialog.Dialog()
choices = get_cas()
#choices = [("EFF", "The EFF Trustify CA"), ("UMich", "The Michigan Trustify CA")]
random.shuffle(choices)
#random.shuffle(choices)
result = d.menu("Pick a Certificate Authority. They're all unique and special!", width=70, choices=choices)
return result
def get_cas():
with open("trustify/client/.ca_offerings") as f:
@ -107,21 +107,22 @@ def by_default():
sys.exit(1)
return result[1] == "Secure"
class progress_shower(object):
# should be taken out if it doesn't break anything
#class progress_shower(object):
# As in "that which shows", not like a rain shower.
def __init__(self, firstmessage="", height=18, width=70):
self.content = firstmessage
self.d = dialog.Dialog()
self.height = height
self.width = width
self.show()
# def __init__(self, firstmessage="", height=18, width=70):
# self.content = firstmessage
# self.d = dialog.Dialog()
# self.height = height
# self.width = width
# self.show()
def add(self, s):
self.content += s
self.show()
#def add(self, s):
# self.content += s
# self.show()
def show(self):
self.d.infobox(self.content, self.height, self.width)
#def show(self):
# self.d.infobox(self.content, self.height, self.width)
def is_hostname_sane(hostname):
"""
@ -288,16 +289,20 @@ def challenge_factory(r, req_filepath, key_filepath, config):
sni_todo.append( (chall.name, dvsni_y, dvsni_nonce, dvsni_ext) )
# TODO: This domain name list is inelegant and the info should be
# gathered from the challenge itself
# gathered from the challenge list itself
dn.append(chall.name)
if chall.type == r.Payment:
url, reason = chall.data
challenges.append(Payment_Challenge(url, reason))
#if chall.type == r.Payment:
# url, reason = chall.data
# challenges.append(Payment_Challenge(url, reason))
#if chall.type == r.Interactive:
# message = chall.data
# challenges.append(Interactive_Challenge(message)
if sni_todo:
# SNI_Challenge can satisfy many sni challenges at once so only
# one "challenge" is issued for all sni_challenges
# one "challenge object" is issued for all sni_challenges
challenges.append(SNI_Challenge(sni_todo, req_filepath, key_filepath, config))
logger.debug(sni_todo)
@ -305,6 +310,9 @@ def challenge_factory(r, req_filepath, key_filepath, config):
def send_request(key_pem, csr_pem, names, quiet=curses):
'''
Sends the request to the CA and returns a response
'''
global server
upstream = "https://%s/chocolate.py" % server
k=chocolatemessage()
@ -428,7 +436,7 @@ def authenticate():
if curses:
names = filter_names(names)
choice_of_ca()
choice = choice_of_ca()
logger.setLogger(logger.NcursesLogger())
logger.setLogLevel(logger.INFO)
else:
@ -457,7 +465,7 @@ def authenticate():
challenges, dn = challenge_factory(r, os.path.abspath(req_file), os.path.abspath(key_file), config)
# Find virtual hosts to deploy certificates too
# Find set of virtual hosts to deploy certificates too
vhost = set()
for name in dn:
host = config.choose_virtual_host(name)

View file

@ -0,0 +1,40 @@
from trustify.client.challenge import Challenge
from trustify.client import logger
import textwrap
############################################################
# Possible addition to challenge structure: priority parameter
# If only DVSNI and Payment are required, the user might want
# to be validated before submitting payment, allowing the user
# to gain confidence in the system. If things do go poorly the
# user has less invested in that particular session/transaction.
#############################################################
###########################################################
# Interactive challlenge displays the string sent by the CA
# formatted to fit on the screen of the client
# The Challenge also adds proper instructions for how the
# client should continue the trustify process
###########################################################
class Interactive_Challenge(Challenge):
BOX_SIZE = 70
def __init__(self, string):
self.string = string
def perform(self, quiet=True):
if quiet:
dialog.Dialog().msgbox(get_display_string(), width=BOX_SIZE)
else:
print get_display_string()
raw_input('')
return True
def get_display_string(self):
return textwrap.fill(self.string, width=BOX_SIZE) + "\n\nPlease Press Enter to Continue"
def formatted_reasons(self):
return "\n\t* %s\n", self.reason

View file

@ -1,9 +1,6 @@
from trustify.client.challenge import Challenge
from trustify.client import logger
# TODO: How is this determined?
curses = True;
############################################################
# Possible addition to challenge structure: priority parameter
# If only DVSNI and Payment are required, the user might want
@ -21,7 +18,7 @@ class Payment_Challenge(Challenge):
self.times_performed = 0
def perform(self, quiet=True):
if curses:
if quiet:
dialog.Dialog().msgbox(get_display_string(), width=70)
else:
print get_display_string()
@ -31,7 +28,7 @@ class Payment_Challenge(Challenge):
return True
def get_display_string():
def get_display_string(self):
if self.times_performed == 0:
return "You are buying " + formatted_reasons() + " You will need to visit " + self.url + " to submit your payment\nPlease press enter once your payment has been submitted"
@ -40,6 +37,6 @@ class Payment_Challenge(Challenge):
return "The CA did not record your payment, please visit " + self.url + " for more information or to finish processing your transaction.\nPress Enter to continue"
def formatted_reasons():
def formatted_reasons(self):
return "\n\t* %s\n", self.reason