summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolderpunk <solderpunk@sdf.org>2020-08-31 21:18:15 +0200
committerSolderpunk <solderpunk@sdf.org>2020-08-31 21:18:15 +0200
commitf45630450f6e7780de4b03c039beae98877e6bb6 (patch)
tree7e8d7a1a6c20f27386c05088fb07a877f50ea320
parent4e8f3dcd058d2c82f6aae43c8161ec3126d552e8 (diff)
Make sure early terminations of _fetch_over_network happen via an exception, not by returning None. Factor out certificate handling interface.
-rwxr-xr-xav98.py96
1 files changed, 51 insertions, 45 deletions
diff --git a/av98.py b/av98.py
index aafb0b1..62d883e 100755
--- a/av98.py
+++ b/av98.py
@@ -190,6 +190,9 @@ CRLF = '\r\n'
def looks_like_url(word):
return "." in word and word.startswith("gemini://")
+class UserAbortException(Exception):
+ pass
+
# GeminiClient Decorators
def needs_gi(inner):
def outer(self, *args, **kwargs):
@@ -335,6 +338,8 @@ you'll be able to transparently follow links to Gopherspace!""")
else:
try:
gi, mime, body, tmpfile = self._fetch_over_network(gi)
+ except UserAbortException:
+ return
except Exception as err:
# Print an error message
if isinstance(err, socket.gaierror):
@@ -385,7 +390,7 @@ you'll be able to transparently follow links to Gopherspace!""")
self._deactivate_client_cert()
else:
print("Staying here.")
-
+ raise UserAbortException()
else:
print("PRIVACY ALERT: Deactivate client cert before connecting to a new domain?")
resp = input("Y/N? ")
@@ -462,7 +467,7 @@ you'll be able to transparently follow links to Gopherspace!""")
else:
follow = "yes"
if follow.strip().lower() not in ("y", "yes"):
- return
+ raise UserAbortException()
self._debug("Following redirect to %s." % new_gi.url)
self._debug("This is consecutive redirect number %d." % len(self.previous_redirectors))
self.previous_redirectors.add(gi.url)
@@ -477,49 +482,8 @@ you'll be able to transparently follow links to Gopherspace!""")
# Client cert
elif status.startswith("6"):
- # Don't do client cert stuff in restricted mode, as in principle
- # it could be used to fill up the disk by creating a whole lot of
- # certificates
- if self.restricted:
- print("The server is requesting a client certificate.")
- print("These are not supported in restricted mode, sorry.")
- return
-
- print("SERVER SAYS: ", meta)
- # Present different messages for different 6x statuses, but
- # handle them the same.
- if status in ("64", "65"):
- print("The server rejected your certificate because it is either expired or not yet valid.")
- elif status == "63":
- print("The server did not accept your certificate.")
- print("You may need to e.g. coordinate with the admin to get your certificate fingerprint whitelisted.")
- else:
- print("The site {} is requesting a client certificate.".format(gi.host))
- print("This will allow the site to recognise you across requests.")
-
- # Give the user choices
- print("What do you want to do?")
- print("1. Give up.")
- print("2. Generate a new transient certificate.")
- print("3. Generate a new persistent certificate.")
- print("4. Load a previously generated persistent.")
- print("5. Load certificate from an external file.")
- choice = input("> ").strip()
- if choice == "2":
- self._generate_transient_cert_cert()
- self._go_to_gi(gi, update_hist, handle)
- elif choice == "3":
- self._generate_persistent_client_cert()
- self._go_to_gi(gi, update_hist, handle)
- elif choice == "4":
- self._choose_client_cert()
- self._go_to_gi(gi, update_hist, handle)
- elif choice == "5":
- self._load_client_cert()
- self._go_to_gi(gi, update_hist, handle)
- else:
- print("Giving up.")
- return
+ self._handle_cert_request(meta)
+ return self._fetch_over_network(gi)
# Invalid status
elif not status.startswith("2"):
@@ -732,6 +696,48 @@ you'll be able to transparently follow links to Gopherspace!""")
for _, filename in self.cache.values():
assert os.path.isfile(filename)
+ def _handle_cert_request(self, meta):
+
+ # Don't do client cert stuff in restricted mode, as in principle
+ # it could be used to fill up the disk by creating a whole lot of
+ # certificates
+ if self.restricted:
+ print("The server is requesting a client certificate.")
+ print("These are not supported in restricted mode, sorry.")
+ raise UserAbortException()
+
+ print("SERVER SAYS: ", meta)
+ # Present different messages for different 6x statuses, but
+ # handle them the same.
+ if status in ("64", "65"):
+ print("The server rejected your certificate because it is either expired or not yet valid.")
+ elif status == "63":
+ print("The server did not accept your certificate.")
+ print("You may need to e.g. coordinate with the admin to get your certificate fingerprint whitelisted.")
+ else:
+ print("The site {} is requesting a client certificate.".format(gi.host))
+ print("This will allow the site to recognise you across requests.")
+
+ # Give the user choices
+ print("What do you want to do?")
+ print("1. Give up.")
+ print("2. Generate a new transient certificate.")
+ print("3. Generate a new persistent certificate.")
+ print("4. Load a previously generated persistent.")
+ print("5. Load certificate from an external file.")
+ choice = input("> ").strip()
+ if choice == "2":
+ self._generate_transient_cert_cert()
+ elif choice == "3":
+ self._generate_persistent_client_cert()
+ elif choice == "4":
+ self._choose_client_cert()
+ elif choice == "5":
+ self._load_client_cert()
+ else:
+ print("Giving up.")
+ raise UserAbortException()
+
def _validate_cert(self, address, host, cert):
"""
Validate a TLS certificate in TOFU mode.