1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-26 07:41:33 +03:00

Merge branch 'master' of github.com:research/chocolate

This commit is contained in:
James Kasten
2012-11-19 01:09:09 -05:00
9 changed files with 38 additions and 34 deletions

View File

@@ -233,6 +233,7 @@ class session(object):
recipient = m.request.recipient
csr = m.request.csr
sig = m.request.sig
self.log("new session from %s" % web.ctx.ip)
# Check whether we are the intended recipient of the request. Doing this
# before the hashcash check is more work for the server but gives a more
# helpful error message (because the hashcash will be wrong automatically
@@ -314,6 +315,7 @@ class session(object):
r.proceed.polldelay = polldelay
def handleexistingsession(self, m, r):
self.log("received message from %s" % web.ctx.ip)
if m.request.IsInitialized():
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/requestinexistingsession")
return

View File

@@ -5,6 +5,9 @@
import time, binascii
from Crypto import Random
import redis
log_redis = redis.Redis()
def signal_handler(a, b):
global clean_shutdown
clean_shutdown = True
@@ -27,6 +30,6 @@ def random_raw():
def log(msg, session = None):
if session:
r.publish("logs", "%s: %s" % (short(session), msg))
log_redis.publish("logs", "%s: %s" % (short(session), msg))
else:
r.publish("logs", "%s" % session)
log_redis.publish("logs", "%s" % session)

View File

@@ -4,7 +4,6 @@
# the database that are waiting for a cert to be issued.
import redis, redis_lock, CSR, sys, signal
from sni_challenge.verify import verify_challenge
from Crypto import Random
r = redis.Redis()
@@ -49,12 +48,12 @@ def issue(session):
return
csr = r.hget(session, "csr")
names = r.lrange("%s:names" % session, 0, -1)
log("attempting to issue certificate for names: %s" % join(names), session)
log("attempting to issue certificate for names: %s" % ", ".join(names), session)
with issue_lock:
cert = CSR.issue(csr, names)
r.hset(session, "cert", cert)
if cert: # once issuing cert succeeded
log("issued certificate for names: %s" % join(names), session)
log("issued certificate for names: %s" % ", ".join(names), session)
r.hset(session, "state", "done")
# r.lpush("pending-done", session)
else: # should not be reached in deployed version

View File

@@ -26,5 +26,6 @@ for message in ps.listen():
if message["channel"] == "exit":
break
if clean_shutdown:
print "logging daemon exiting cleanly"
sys.stdout.write("logging daemon exiting cleanly\n")
sys.stdout.flush()
break

View File

@@ -25,7 +25,7 @@ def makechallenge(session):
# pending-requests queue and not pushed into any other queue.
# We don't have to remove it from pending-makechallenge
# because the caller has already done so.
if debug: print "removing expired session", short(session)
log("removing expired session", session)
r.lrem("pending-requests", session)
return
# Currently only makes challenges of type 0 (DomainValidateSNI)
@@ -37,9 +37,8 @@ def makechallenge(session):
# Make one challenge for each name. (This one-to-one relationship
# is not an inherent protocol requirement!)
names = r.lrange("%s:names" % session, 0, -1)
if debug: print "%s: new valid request" % session
if debug: print "%s: from requesting client at %s" % (short(session), r.hget(session, "client-addr"))
if debug: print "%s: for %d names: %s" % (short(session), len(names), ", ".join(names))
log("new valid request from requesting client at %s" % r.hget(session, "client-addr"), session)
log("for %d names: %s" % (len(names), ", ".join(names)), session)
for i, name in enumerate(names):
challenge = "%s:%d" % (session, i)
r.hset(challenge, "challtime", int(time.time()))
@@ -52,7 +51,7 @@ def makechallenge(session):
r.hset(challenge, "dvsni:ext", "1.3.3.7")
# Keep accurate count of how many challenges exist in this session.
r.hincrby(session, "challenges", 1)
if debug: print "created new challenge", short(challenge)
log("created new challenge %s" % challenge, session)
if True: # challenges have been created
r.hset(session, "state", "testchallenge")
else:

View File

@@ -47,7 +47,7 @@ for message in ps.listen():
if len(session) != 64: continue
if session not in r or r.hget(session, "live") != "True": continue
if r.hget(session, "state") != "payment": continue
if debug: print "\t** All challenges satisfied; payment received; request %s GRANTED" % short(session)
log("\t** All challenges satisfied; payment received; request GRANTED", session)
r.hset(session, "state", "issue")
r.lpush("pending-issue", session)
continue

View File

@@ -30,11 +30,11 @@ class payment(object):
def GET(self, session):
web.header("Content-type", "text/html")
if len(session) != 64 or not all(hexdigit(s) for s in session):
return "Attempt to process payment for invalid session."
return "<html><h1>Oops!</h1>Attempt to process payment for invalid session.</html>"
if session not in r or r.hget(session, "live") != "True":
return "Attempt to process payment for invalid session."
return "<html><h1>Oops!</h1>Attempt to process payment for invalid session.</html>"
if r.hget(session, "state") != "payment":
return "Attempt to process payment for session not expecting it."
return "<html><h1>Oops!</h1>Attempt to process payment for session that was not expecting it.</html>"
r.publish("payments", session)
names = r.lrange("%s:names" % session, 0, -1)
names_list = '<ul style="font-family:monospace">' + "\n".join("<li>%s</li>" % n for n in names) + '</ul>'

View File

@@ -68,16 +68,17 @@ def verify_challenge(address, r, nonce, socksify=False):
sni_support.set_sni_ext(conn.ssl, sni_name)
try:
conn.connect((address, 443))
peername = str(conn.socket.getpeername())
except Exception, e:
return False, "Connection to SSL Server failed (%s)" % str(e)
return False, "Connection to SSL Server failed (%s)" % str(e), peername
cert_chain = conn.get_peer_cert_chain()
#Ensure certificate chain form is correct
if cert_chain is None:
return False, "Client did not provide a certificate"
return False, "Client did not provide a certificate", peername
if len(cert_chain) != 1:
return False, "Chocolate client should only include 1 cert"
return False, "Chocolate client should only include 1 cert", peername
for i in range(0,cert_chain[0].get_ext_count()):
ext = cert_chain[0].get_ext_at(i)
@@ -87,11 +88,11 @@ def verify_challenge(address, r, nonce, socksify=False):
valid = check_challenge_value(sni_support.get_unknown_value(ext.x509_ext), r)
if valid:
return True, "Challenge completed successfully"
return True, "Challenge completed successfully", peername
else:
return False, "Certificate extension does not check out"
return False, "Certificate extension does not check out", peername
return False, "Chocolate extension not included in certificate"
return False, "Chocolate extension not included in certificate", peername
def main():
#Testing the example sni_challenge
@@ -108,10 +109,10 @@ def main():
nonce = binascii.hexlify(nonce)
nonce2 = binascii.hexlify(nonce2)
valid, response = verify_challenge("example.com", r, nonce)
valid, response, peername = verify_challenge("example.com", r, nonce)
#valid, response = verify_challenge("127.0.0.1", r, nonce)
print response
valid, response = verify_challenge("www.example.com", r2, nonce2)
valid, response, peername = verify_challenge("www.example.com", r2, nonce2)
#valid, response = verify_challenge("localhost", r2, nonce2)
print response
if __name__ == "__main__":

View File

@@ -34,7 +34,7 @@ def testchallenge(session):
# pending-requests queue and not pushed into any other queue.
# We don't have to remove it from pending-testchallenge
# because the caller has already done so.
if debug: print "removing expired session", short(session)
log("removing expired session", session)
r.lrem("pending-requests", session)
return
if r.hget(session, "state") != "testchallenge":
@@ -49,7 +49,7 @@ def testchallenge(session):
all_satisfied = True
for i, name in enumerate(r.lrange("%s:names" % session, 0, -1)):
challenge = "%s:%d" % (session, i)
if debug: print "testing challenge", short(challenge)
log("testing challenge %s" % challenge, session)
challtime = int(r.hget(challenge, "challtime"))
challtype = int(r.hget(challenge, "type"))
name = r.hget(challenge, "name")
@@ -59,15 +59,14 @@ def testchallenge(session):
if not satisfied and not failed:
# if debug: print "challenge", short(challenge), "being tested"
if challtype == 0: # DomainValidateSNI
if debug: print "\tbeginning dvsni test to %s" % name
log("\tbeginning dvsni test to %s" % name, session)
dvsni_nonce = r.hget(challenge, "dvsni:nonce")
dvsni_r = r.hget(challenge, "dvsni:r")
dvsni_ext = r.hget(challenge, "dvsni:ext")
direct_result, direct_reason = verify_challenge(name, dvsni_r, dvsni_nonce, False)
proxy_result, proxy_reason = verify_challenge(name, dvsni_r, dvsni_nonce, True)
if debug:
print "\t...direct probe: %s (%s)" % (direct_result, direct_reason)
print "\tTor proxy probe: %s (%s)" % (proxy_result, proxy_reason)
direct_result, direct_reason, direct_peername = verify_challenge(name, dvsni_r, dvsni_nonce, False)
proxy_result, proxy_reason, proxy_peername = verify_challenge(name, dvsni_r, dvsni_nonce, True)
log("\t...direct probe: %s (%s) to %s" % (direct_result, direct_reason, direct_peername), session)
log("\tTor proxy probe: %s (%s)" % (proxy_result, proxy_reason), session)
if direct_result and proxy_result:
r.hset(challenge, "satisfied", True)
else:
@@ -80,7 +79,7 @@ def testchallenge(session):
# Don't know how to handle this challenge type
all_satisfied = False
elif not satisfied:
if debug: print "\tchallenge was not attempted"
log("\tchallenge was not attempted", session)
all_satisfied = False
if all_satisfied:
# Challenges all succeeded, so we should prepare to issue
@@ -91,7 +90,7 @@ def testchallenge(session):
# the daemon that put this session on the queue should
# also have implicitly guaranteed this).
if policy.payment_required(session):
if debug: print "\t** All challenges satisfied; request %s NEEDS PAYMENT" % short(session)
log("\t** All challenges satisfied; request NEEDS PAYMENT", session)
# Try to get a unique abbreviated ID (10 hex digits)
for i in xrange(20):
abbreviation = random()[:10]
@@ -110,7 +109,7 @@ def testchallenge(session):
# instantaneously as soon as the payment system sends a "payments"
# pubsub message to the payments daemon.
else:
if debug: print "\t** All challenges satisfied; request %s GRANTED" % short(session)
log("\t** All challenges satisfied; request GRANTED", session)
r.hset(session, "state", "issue")
r.lpush("pending-issue", session)
else: