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

error_uri to allow displaying useful error messages from server

This commit is contained in:
Seth Schoen
2012-11-18 22:12:28 -08:00
parent 83d243923d
commit 445ed85774
2 changed files with 24 additions and 21 deletions

View File

@@ -6,6 +6,9 @@ chocolate_server_name = "ca.theobroma.info"
# called followed by a slash and then the 64 hex digit session ID)
payment_uri = "https://ca.theobroma.info/payment.py"
# Where are on-line error messages about failures located?
error_uri = "https://ca.theobroma.info/failures/"
# The shortest length in bits of an acceptable RSA modulus.
min_keysize = 2048

View File

@@ -12,7 +12,7 @@ from google.protobuf.message import DecodeError
from CONFIG import chocolate_server_name, min_keysize, difficulty, polldelay
from CONFIG import max_names, max_csr_size, maximum_session_age
from CONFIG import maximum_challenge_age, hashcash_expiry, extra_name_blacklist
from CONFIG import cert_chain_file, debug, payment_uri
from CONFIG import cert_chain_file, debug, payment_uri, error_uri
poll_interval = 10
@@ -153,7 +153,7 @@ class session(object):
# Whoops!
pass
else:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/internalerror")
self.die(r, r.BadRequest, uri="%sinternalerror" % error_uri)
return
def check_hashcash(self, h, n):
@@ -177,14 +177,14 @@ class session(object):
# Check for some ways in which the message from the client
# can be inappropriate.
if m.challenge or m.proceed.IsInitialized() or m.success.IsInitialized():
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/invalidfromclient")
self.die(r, r.BadRequest, uri="%sinvalidfromclient" % error_uri)
return
distinct_messages = 0
if m.request.IsInitialized(): distinct_messages += 1
if m.failure.IsInitialized(): distinct_messages += 1
if m.completedchallenge: distinct_messages += 1
if distinct_messages > 1:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/mixedmessages")
self.die(r, r.BadRequest, uri="%smixedmessages" % error_uri)
return
# The rule that a new session must contain a request is enforced
# by handlenewsession. The rule that an existing session must
@@ -203,7 +203,7 @@ class session(object):
r.session = ""
if not safe("session", m.session):
# Note that self.id is still uninitialized here.
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/illegalsession")
self.die(r, r.BadRequest, uri="%sillegalsession" % error_uri)
return
self.id = m.session
r.session = m.session
@@ -227,7 +227,7 @@ class session(object):
if r.failure.IsInitialized(): return
if not m.request.IsInitialized():
# It is mandatory to make a signing request at the outset of a session.
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/missingrequest")
self.die(r, r.BadRequest, uri="%smissingrequest" % error_uri)
return
timestamp = m.request.timestamp
recipient = m.request.recipient
@@ -239,18 +239,18 @@ class session(object):
# helpful error message (because the hashcash will be wrong automatically
# if it's addressed to a different server!).
if recipient != chocolate_server_name:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/recipient")
self.die(r, r.BadRequest, uri="%srecipient" % error_uri)
return
# Check hashcash before doing any crypto or database access.
names = CSR.subject_names(csr)
if not m.request.clientpuzzle or not self.check_hashcash(m.request.clientpuzzle, len(names)):
self.die(r, r.NeedClientPuzzle, uri="https://ca.example.com/failures/hashcash")
self.die(r, r.NeedClientPuzzle, uri="%shashcash" % error_uri)
return
if self.request_made():
# Can't make new signing requests if there have already been requests in
# this session. (All signing requests should occur together at the
# beginning.)
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/priorrequest")
self.die(r, r.BadRequest, uri="%spriorrequest" % error_uri)
return
# Process the request.
# TODO: check that each element of the CA/B Forum Baseline
@@ -258,16 +258,16 @@ class session(object):
# TODO: check that the request involves a public key algorithm
# that we support.
if not all([safe("recipient", recipient), safe("csr", csr)]):
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/illegalcharacter")
self.die(r, r.BadRequest, uri="%sillegalcharacter" % error_uri)
return
if timestamp - time.time() > 5:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/future")
self.die(r, r.BadRequest, uri="%sfuture" % error_uri)
return
if time.time() - timestamp > 100:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/past")
self.die(r, r.BadRequest, uri="%spast" % error_uri)
return
if len(csr) > max_csr_size:
self.die(r, r.BadCSR, uri="https://ca.example.com/failures/longcsr")
self.die(r, r.BadCSR, uri="%slongcsr" % error_uri)
return
if not CSR.parse(csr):
self.die(r, r.BadCSR)
@@ -283,23 +283,23 @@ class session(object):
self.die(r, r.BadCSR)
return
if len(names) > max_names:
self.die(r, r.BadCSR, uri="https://ca.example.com/failures/toomanynames")
self.die(r, r.BadCSR, uri="%stoomanynames" % error_uri)
return
for san in names: # includes CN as well as SANs
if not safe("hostname", san) or not CSR.can_sign(san) or san in extra_name_blacklist:
# TODO: Is there a problem including client-supplied data in the URL?
self.die(r, r.CannotIssueThatName, uri="https://ca.example.com/failures/name?%s" % san)
self.die(r, r.CannotIssueThatName, uri="%sname?%s" % (error_uri,san))
return
try:
# Check whether the SSL Observatory has seen a valid cert for this name.
# XXX: This has been disabled because this API is unavailable
# or unreliable.
if False and urllib2.urlopen("https://observatory.eff.org/check_name?domain_name=%s" % san).read().strip() != "False":
self.die(r, r.CannotIssueThatName, uri="https://ca.example.com/failures/observatory?%s" % san)
self.die(r, r.CannotIssueThatName, uri="%sobservatory?%s" % (error_uri,san))
return
wildcard_variant = "*." + san.partition(".")[2]
if False and urllib2.urlopen("https://observatory.eff.org/check_name?domain_name=%s" % wildcard_variant).read().strip() != "False":
self.die(r, r.CannotIssueThatName, uri="https://ca.example.com/failures/observatory?%s" % san)
self.die(r, r.CannotIssueThatName, uri="%sobservatory?%s" % (error_uri,san))
return
except urllib2.HTTPError:
# Currently, don't consider it fatal if the Observatory blacklist
@@ -317,14 +317,14 @@ class session(object):
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")
self.die(r, r.BadRequest, uri="%srequestinexistingsession" % error_uri)
return
# The caller has verified that this session exists and is live.
# If we have no state, something is crazy (maybe a race from two
# instances of the client?).
state = self.state()
if state is None:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/uninitializedsession")
self.die(r, r.BadRequest, uri="%suninitializedsession" % error_uri)
return
# If we're in makechallenge or issue, tell the client to come back later.
if state == "makechallenge" or state == "issue":
@@ -362,7 +362,7 @@ class session(object):
self.send_cert(m, r)
return
# Unknown session status.
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/internalerror")
self.die(r, r.BadRequest, uri="%sinternalerror" % error_uri)
return
# TODO: Process challenge-related messages from the client.
@@ -391,7 +391,7 @@ class session(object):
# Currently, we can only handle challenge type 0 (dvsni)
# TODO: unify names "succeeded" vs. "satisfied"?
if int(c["type"]) != 0:
self.die(r, r.BadRequest, uri="https://ca.example.com/failures/internalerror")
self.die(r, r.BadRequest, uri="%sinternalerror" % error_uri)
return
chall = r.challenge.add()
chall.type = int(c["type"])