some reorganization and a start toward processing requests

This commit is contained in:
Seth Schoen
2012-05-31 13:22:33 -07:00
parent da47a260bc
commit 7aceaba6f0
+88 -15
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import web, shelve, time import web, shelve, time
import CSR
from Crypto.Hash import SHA256, HMAC from Crypto.Hash import SHA256, HMAC
from Crypto import Random from Crypto import Random
from chocolate_protocol_pb2 import chocolatemessage from chocolate_protocol_pb2 import chocolatemessage
@@ -42,11 +43,91 @@ class sessionstore(object):
def age(self, session): def age(self, session):
return int(time.time()) - self.f[session]["created"] return int(time.time()) - self.f[session]["created"]
def make_request(self, session, request):
self.f["request"] = request
def get_request(self, session):
return self.f["request"]
def request_made(self, session):
return "request" in self.f[session]
class index: class index:
def GET(self): def GET(self):
web.header("Content-type", "text/html") web.header("Content-type", "text/html")
return "Hello, world! This server only accepts POST requests." return "Hello, world! This server only accepts POST requests."
def killsession(self):
self.sessions.kill(self.session)
def handlesession(self, m, r):
if m.session == "":
# New session
r.session = SHA256.new(Random.get_random_bytes(32)).hexdigest()
self.session = r.session.encode("UTF8")
self.sessions.create(self.session, int(time.time()))
elif m.session and not r.failure.IsInitialized():
self.session = m.session.encode("UTF8")
r.session = self.session
if not self.sessions.exists(self.session):
r.failure.cause = r.StaleRequest
elif not self.sessions.live(self.session):
r.failure.cause = r.StaleRequest
elif self.sessions.age(self.session) > MaximumSessionAge:
self.killsession()
r.failure.cause = r.StaleRequest
def handleclientfailure(self, m, r):
if r.failure.IsInitialized(): return
if m.failure.IsInitialized():
# Received failure message from client!
self.killsession()
r.failure.cause = r.AbandonedRequest
def handlesigningrequest(self, m, r):
if r.failure.IsInitialized(): return
if not m.request: return
if self.sessions.request_made(self.session):
self.killsession()
r.failure.cause = r.BadRequest
r.failure.uri = "https://ca.example.com/failures/request"
return
# TODO: currently only examine the first request
# TODO: check client puzzle
timestamp = m.request[0].timestamp
recipient = m.request[0].recipient
nonce = m.request[0].nonce
csr = m.request[0].csr
sig = m.request[0].sig
if timestamp > time.time() or time.time() - timestamp > 100:
self.killsession()
r.failure.cause = r.BadRequest
r.failure.affectedrequest = nonce
r.failure.uri = "https://ca.example.com/failures/time"
return
if recipient != "ca.example.com":
self.killsession()
r.failure.cause = r.BadRequest
r.failure.affectedrequest = nonce
r.failure.uri = "https://ca.example.com/failures/recipient"
return
if not CSR.parse(csr):
self.killsession()
r.failure.cause = r.BadCSR
r.failure.affectedrequest = nonce
return
# if CSR.verify(pubkey(csr), sig) != hmac("chocolate-request-ca-example.com", /%s/%s/%s/%s" % (timestamp, recipient, nonce, csr))):
# self.killsession()
# r.failure.cause = BadSignature
# r.failure.affectedrequest = nonce
# self.killsession()
# return
if not CSR.goodkey(csr):
self.killsession()
r.failure.cause = r.UnsafeKey
r.failure.affectedrequest = nonce
return
def POST(self): def POST(self):
web.header("Content-type", "application/x-protobuf") web.header("Content-type", "application/x-protobuf")
# web.setcookie("chocolate", hmac("foo", "bar"), # web.setcookie("chocolate", hmac("foo", "bar"),
@@ -62,21 +143,13 @@ class index:
else: else:
if m.chocolateversion != 1: if m.chocolateversion != 1:
r.failure.cause = r.UnsupportedVersion r.failure.cause = r.UnsupportedVersion
if m.session == "": self.handlesession(m, r)
# New session
r.session = SHA256.new(Random.get_random_bytes(32)).hexdigest() self.handleclientfailure(m, r)
session = r.session.encode("UTF8")
self.sessions.create(session, int(time.time())) self.handlesigningrequest(m, r)
elif m.session and not r.failure.IsInitialized():
session = m.session.encode("UTF8") # Send reply
r.session = session
if not self.sessions.exists(session):
r.failure.cause = r.StaleRequest
elif not self.sessions.live(session):
r.failure.cause = r.StaleRequest
elif self.sessions.age(session) > MaximumSessionAge:
self.sessions.kill(session)
r.failure.cause = r.StaleRequest
if m.debug: if m.debug:
web.header("Content-type", "text/plain") web.header("Content-type", "text/plain")
return "SAW MESSAGE: %s\n" % str(r) return "SAW MESSAGE: %s\n" % str(r)