mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 18:56:55 +02:00
some reorganization and a start toward processing requests
This commit is contained in:
+88
-15
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user