feat: stapler challenge for self discovery
This commit is contained in:
+17
-2
@@ -289,6 +289,7 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
|
|||||||
protocol_version = "HTTP/1.1"
|
protocol_version = "HTTP/1.1"
|
||||||
server_version = "StaplerServer/" + PKG_VERSION
|
server_version = "StaplerServer/" + PKG_VERSION
|
||||||
CERTBOT_CHALLENGE_PATH = "/.well-known/acme-challenge"
|
CERTBOT_CHALLENGE_PATH = "/.well-known/acme-challenge"
|
||||||
|
STAPLER_CHALLENGE_PATH = "/.well-known/stapler"
|
||||||
UPDATE_PATH_REGEX = re.compile(r"^\/([\w-]+)\/?$")
|
UPDATE_PATH_REGEX = re.compile(r"^\/([\w-]+)\/?$")
|
||||||
GET_PATH_REGEX = re.compile(r"^\/([\w-]+)($|\/)")
|
GET_PATH_REGEX = re.compile(r"^\/([\w-]+)($|\/)")
|
||||||
HOST_PART_REGEX = re.compile(r"^([a-z0-9]|[a-z0-9][a-z0-9-]{,61}[a-z0-9])$")
|
HOST_PART_REGEX = re.compile(r"^([a-z0-9]|[a-z0-9][a-z0-9-]{,61}[a-z0-9])$")
|
||||||
@@ -405,6 +406,8 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
|
|||||||
self._pre_log_request()
|
self._pre_log_request()
|
||||||
if self._proxy_or_redirect():
|
if self._proxy_or_redirect():
|
||||||
return None
|
return None
|
||||||
|
if self._is_stapler_challenge(self.path):
|
||||||
|
return self.send_status_only(http.HTTPStatus.NO_CONTENT)
|
||||||
if self.path == "/" and self.host == self.default_host:
|
if self.path == "/" and self.host == self.default_host:
|
||||||
return self.send_basic_body(self.server_signature())
|
return self.send_basic_body(self.server_signature())
|
||||||
super().do_HEAD()
|
super().do_HEAD()
|
||||||
@@ -417,6 +420,8 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
|
|||||||
self._pre_log_request()
|
self._pre_log_request()
|
||||||
if self._proxy_or_redirect():
|
if self._proxy_or_redirect():
|
||||||
return None
|
return None
|
||||||
|
if self._is_stapler_challenge(self.path):
|
||||||
|
return self.send_status_only(http.HTTPStatus.NO_CONTENT)
|
||||||
if self.path == "/" and self.host == self.default_host:
|
if self.path == "/" and self.host == self.default_host:
|
||||||
return self.send_basic_body(self.server_signature())
|
return self.send_basic_body(self.server_signature())
|
||||||
super().do_GET()
|
super().do_GET()
|
||||||
@@ -545,7 +550,11 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _proxy_or_redirect(self) -> bool:
|
def _proxy_or_redirect(self) -> bool:
|
||||||
if self.has_token or self._is_certbot_challenge(self.path):
|
if (
|
||||||
|
self.has_token
|
||||||
|
or self._is_certbot_challenge(self.path)
|
||||||
|
or self._is_stapler_challenge(self.path)
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
if (page := self.__get_page(self.path)) is None:
|
if (page := self.__get_page(self.path)) is None:
|
||||||
return False
|
return False
|
||||||
@@ -570,6 +579,9 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler, BaseHandler):
|
|||||||
self.certbot_www + path
|
self.certbot_www + path
|
||||||
).resolve().is_relative_to(self.certbot_www)
|
).resolve().is_relative_to(self.certbot_www)
|
||||||
|
|
||||||
|
def _is_stapler_challenge(self, path: str) -> bool:
|
||||||
|
return path.startswith(self.STAPLER_CHALLENGE_PATH)
|
||||||
|
|
||||||
@typing.override
|
@typing.override
|
||||||
def translate_path(self, path: str) -> str:
|
def translate_path(self, path: str) -> str:
|
||||||
if self._is_certbot_challenge(path):
|
if self._is_certbot_challenge(path):
|
||||||
@@ -664,7 +676,10 @@ class UpgradeHandler(RequestHandler):
|
|||||||
def do_HEAD(self) -> None:
|
def do_HEAD(self) -> None:
|
||||||
with self.handle_errors():
|
with self.handle_errors():
|
||||||
self._pre_log_request()
|
self._pre_log_request()
|
||||||
self.send_redirect(f"https://{self.host}{self.path}")
|
if self._is_stapler_challenge(self.path):
|
||||||
|
self.send_status_only(http.HTTPStatus.NO_CONTENT)
|
||||||
|
else:
|
||||||
|
self.send_redirect(f"https://{self.host}{self.path}")
|
||||||
self.close_connection = True
|
self.close_connection = True
|
||||||
|
|
||||||
def do_GET(self) -> None:
|
def do_GET(self) -> None:
|
||||||
|
|||||||
@@ -204,6 +204,17 @@ class TestRequestHandler(BaseHandlerTestCase):
|
|||||||
):
|
):
|
||||||
handler.do_HEAD()
|
handler.do_HEAD()
|
||||||
|
|
||||||
|
def test_do_head_stapler(self) -> None:
|
||||||
|
handler = self._get_handler("/.well-known/stapler/something")
|
||||||
|
with (
|
||||||
|
self.expects_status_only(
|
||||||
|
handler,
|
||||||
|
http.HTTPStatus.NO_CONTENT,
|
||||||
|
),
|
||||||
|
self.seal_mocks(),
|
||||||
|
):
|
||||||
|
handler.do_HEAD()
|
||||||
|
|
||||||
def test_do_head_forward(self) -> None:
|
def test_do_head_forward(self) -> None:
|
||||||
handler = self._get_handler("/file")
|
handler = self._get_handler("/file")
|
||||||
with (
|
with (
|
||||||
@@ -222,6 +233,17 @@ class TestRequestHandler(BaseHandlerTestCase):
|
|||||||
):
|
):
|
||||||
handler.do_GET()
|
handler.do_GET()
|
||||||
|
|
||||||
|
def test_do_get_stapler(self) -> None:
|
||||||
|
handler = self._get_handler("/.well-known/stapler/something")
|
||||||
|
with (
|
||||||
|
self.expects_status_only(
|
||||||
|
handler,
|
||||||
|
http.HTTPStatus.NO_CONTENT,
|
||||||
|
),
|
||||||
|
self.seal_mocks(),
|
||||||
|
):
|
||||||
|
handler.do_GET()
|
||||||
|
|
||||||
def test_do_get_forward_on_other_path(self) -> None:
|
def test_do_get_forward_on_other_path(self) -> None:
|
||||||
handler = self._get_handler("/file")
|
handler = self._get_handler("/file")
|
||||||
with (
|
with (
|
||||||
@@ -1373,3 +1395,14 @@ class TestUpgradeHandler(BaseHandlerTestCase):
|
|||||||
self.seal_mocks(),
|
self.seal_mocks(),
|
||||||
):
|
):
|
||||||
handler.do_HEAD()
|
handler.do_HEAD()
|
||||||
|
|
||||||
|
def test_do_head_stapler(self) -> None:
|
||||||
|
handler = self._get_handler("/.well-known/stapler/something")
|
||||||
|
with (
|
||||||
|
self.expects_status_only(
|
||||||
|
handler,
|
||||||
|
http.HTTPStatus.NO_CONTENT,
|
||||||
|
),
|
||||||
|
self.seal_mocks(),
|
||||||
|
):
|
||||||
|
handler.do_HEAD()
|
||||||
|
|||||||
Reference in New Issue
Block a user