Пример #1
0
    def _perform_single(self, achall):
        # same path for each challenge response would be easier for
        # users, but will not work if multiple domains point at the
        # same server: default command doesn't support virtual hosts
        response = challenges.SimpleHTTPResponse(
            path=jose.b64encode(os.urandom(18)),
            tls=(not self.config.no_simple_http_tls))
        assert response.good_path  # is encoded os.urandom(18) good?

        self._notify_and_wait(
            self.MESSAGE_TEMPLATE.format(
                achall=achall,
                response=response,
                uri=response.uri(achall.domain),
                ct=response.CONTENT_TYPE,
                command=self.template.format(
                    achall=achall,
                    response=response,
                    ct=response.CONTENT_TYPE,
                    port=(response.port if self.config.simple_http_port is None
                          else self.config.simple_http_port))))

        if response.simple_verify(achall.challb, achall.domain,
                                  self.config.simple_http_port):
            return response
        else:
            return None
Пример #2
0
    def _test_simple_http(self, add):
        chall = challenges.SimpleHTTP(token=(b'x' * 16))
        response = challenges.SimpleHTTPResponse(tls=False)

        from acme.standalone import SimpleHTTPRequestHandler
        resource = SimpleHTTPRequestHandler.SimpleHTTPResource(
            chall=chall, response=response, validation=response.gen_validation(
                chall, self.account_key))
        if add:
            self.resources.add(resource)
        return resource.response.simple_verify(
            resource.chall, 'localhost', self.account_key.public_key(),
            port=self.port)
Пример #3
0
    def setUp(self):
        self.responses = (
            challenges.SimpleHTTPResponse(path='Hf5GrX4Q7EBax9hc2jJnfw'),
            None,  # null
            challenges.RecoveryTokenResponse(token='23029d88d9e123e'),
        )
        self.contact = ("mailto:[email protected]", "tel:+12025551212")
        signature = other.Signature(
            alg=jose.RS256,
            jwk=jose.JWKRSA(key=KEY.publickey()),
            sig='-v\xd8\xc2\xa3\xba0\xd6\x92\x16\xb5.\xbe\xa1[\x04\xbe'
            '\x1b\xa1X\xd2)\x18\x94\x8f\xd7\xd0\xc0\xbbcI`W\xdf v'
            '\xe4\xed\xe8\x03J\xe8\xc8<?\xc8W\x94\x94cj(\xe7\xaa$'
            '\x92\xe9\x96\x11\xc2\xefx\x0bR',
            nonce='\xab?\x08o\xe6\x81$\x9f\xa1\xc9\x025\x1c\x1b\xa5+')

        from acme.messages import AuthorizationRequest
        self.msg = AuthorizationRequest(
            session_id='aefoGaavieG9Wihuk2aufai3aeZ5EeW4',
            nonce='\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9',
            responses=self.responses,
            signature=signature,
            contact=self.contact,
        )

        self.jmsg_to = {
            'type': 'authorizationRequest',
            'sessionID': 'aefoGaavieG9Wihuk2aufai3aeZ5EeW4',
            'nonce': '7Nbyb1lI6xPVI3Hg3aKSqQ',
            'responses': self.responses,
            'signature': signature,
            'contact': self.contact,
        }
        self.jmsg_from = {
            'type':
            'authorizationRequest',
            'sessionID':
            'aefoGaavieG9Wihuk2aufai3aeZ5EeW4',
            'nonce':
            '7Nbyb1lI6xPVI3Hg3aKSqQ',
            'responses': [
                None if response is None else response.to_json()
                for response in self.responses
            ],
            'signature':
            signature.to_json(),
            # TODO: schema validation doesn't recognize tuples as
            # arrays :(
            'contact':
            list(self.contact),
        }
Пример #4
0
    def test_perform(self, mock_raw_input, mock_verify, mock_stdout):
        mock_verify.return_value = True

        resp = challenges.SimpleHTTPResponse(tls=False)
        self.assertEqual([resp], self.auth.perform(self.achalls))
        self.assertEqual(1, mock_raw_input.call_count)
        mock_verify.assert_called_with(self.achalls[0].challb.chall, "foo.com",
                                       KEY.public_key(), 4430)

        message = mock_stdout.write.mock_calls[0][1][0]
        self.assertTrue(self.achalls[0].chall.encode("token") in message)

        mock_verify.return_value = False
        self.assertEqual([None], self.auth.perform(self.achalls))
Пример #5
0
    def _perform_single(self, achall):
        # same path for each challenge response would be easier for
        # users, but will not work if multiple domains point at the
        # same server: default command doesn't support virtual hosts
        response = challenges.SimpleHTTPResponse(
            path=jose.b64encode(os.urandom(18)),
            tls=(not self.config.no_simple_http_tls))
        assert response.good_path  # is encoded os.urandom(18) good?

        command = self.template.format(
            root=self._root, achall=achall, response=response,
            ct=response.CONTENT_TYPE, port=(
                response.port if self.config.simple_http_port is None
                else self.config.simple_http_port))
        if self.conf("test-mode"):
            logger.debug("Test mode. Executing the manual command: %s", command)
            try:
                self._httpd = subprocess.Popen(
                    command,
                    # don't care about setting stdout and stderr,
                    # we're in test mode anyway
                    shell=True,
                    # "preexec_fn" is UNIX specific, but so is "command"
                    preexec_fn=os.setsid)
            except OSError as error:  # ValueError should not happen!
                logger.debug(
                    "Couldn't execute manual command: %s", error, exc_info=True)
                return False
            logger.debug("Manual command running as PID %s.", self._httpd.pid)
            # give it some time to bootstrap, before we try to verify
            # (cert generation in case of simpleHttpS might take time)
            time.sleep(4)  # XXX
            if self._httpd.poll() is not None:
                raise errors.Error("Couldn't execute manual command")
        else:
            self._notify_and_wait(self.MESSAGE_TEMPLATE.format(
                achall=achall, response=response,
                uri=response.uri(achall.domain), ct=response.CONTENT_TYPE,
                command=command))

        if response.simple_verify(
                achall.challb, achall.domain, self.config.simple_http_port):
            return response
        else:
            if self.conf("test-mode") and self._httpd.poll() is not None:
                # simply verify cause command failure...
                return False
            return None
Пример #6
0
    def test_perform(self, mock_raw_input, mock_verify, mock_urandom,
                     mock_stdout):
        mock_urandom.return_value = "foo"
        mock_verify.return_value = True

        resp = challenges.SimpleHTTPResponse(tls=False, path='Zm9v')
        self.assertEqual([resp], self.auth.perform(self.achalls))
        mock_raw_input.assert_called_once()
        mock_verify.assert_called_with(self.achalls[0].challb, "foo.com", 4430)

        message = mock_stdout.write.mock_calls[0][1][0]
        self.assertTrue(self.achalls[0].token in message)
        self.assertTrue('Zm9v' in message)

        mock_verify.return_value = False
        self.assertEqual([None], self.auth.perform(self.achalls))
Пример #7
0
    def gen_response_and_validation(self, tls):
        """Generates a SimpleHTTP response and validation.

        :param bool tls: True if TLS should be used

        :returns: ``(response, validation)`` tuple, where ``response`` is
            an instance of `acme.challenges.SimpleHTTPResponse` and
            ``validation`` is an instance of
            `acme.challenges.SimpleHTTPProvisionedResource`.
        :rtype: tuple

        """
        response = challenges.SimpleHTTPResponse(tls=tls)

        validation = response.gen_validation(self.challb.chall,
                                             self.account_key)
        logger.debug("Simple HTTP validation payload: %s", validation.payload)
        return response, validation
Пример #8
0
    def test_perform(self, mock_raw_input, mock_get, mock_urandom, mock_stdout):
        mock_urandom.return_value = "foo"
        mock_get().text = self.achalls[0].token

        self.assertEqual(
            [challenges.SimpleHTTPResponse(tls=False, path='Zm9v')],
            self.auth.perform(self.achalls))
        mock_raw_input.assert_called_once()
        mock_get.assert_called_with(
            "http://foo.com/.well-known/acme-challenge/Zm9v", verify=False)

        message = mock_stdout.write.mock_calls[0][1][0]
        self.assertTrue(self.achalls[0].token in message)
        self.assertTrue('Zm9v' in message)

        mock_get().text = self.achalls[0].token + '!'
        self.assertEqual([None], self.auth.perform(self.achalls))

        mock_get.side_effect = requests.exceptions.ConnectionError
        self.assertEqual([None], self.auth.perform(self.achalls))
Пример #9
0
    def test_perform(self, mock_raw_input, mock_verify, mock_urandom,
                     mock_stdout):
        mock_urandom.side_effect = nonrandom_urandom
        mock_verify.return_value = True

        resp = challenges.SimpleHTTPResponse(tls=False)
        self.assertEqual([resp], self.auth.perform(self.achalls))
        self.assertEqual(1, mock_raw_input.call_count)
        mock_verify.assert_called_with(self.achalls[0].challb.chall, "foo.com",
                                       KEY.public_key(), 4430)

        message = mock_stdout.write.mock_calls[0][1][0]
        self.assertEqual(
            message, """\
Make sure your web server displays the following content at
http://foo.com/.well-known/acme-challenge/ZXZhR3hmQURzNnBTUmIyTEF2OUlaZjE3RHQzanV4R0orUEN0OTJ3citvQQ before continuing:

{"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp580rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogIlpYWmhSM2htUVVSek5uQlRVbUl5VEVGMk9VbGFaakUzUkhRemFuVjRSMG9yVUVOME9USjNjaXR2UVEiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "jFPJFC-2eRyBw7Sl0wyEBhsdvRZtKk8hc6HykEPAiofZlIwdIu76u2xHqMVZWSZdpxwMNUnnawTEAqgMWFydMA"}

Content-Type header MUST be set to application/jose+json.

If you don\'t have HTTP server configured, you can run the following
command on the target server (as root):

mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge
cd /tmp/letsencrypt/public_html
echo -n \'{"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp580rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogIlpYWmhSM2htUVVSek5uQlRVbUl5VEVGMk9VbGFaakUzUkhRemFuVjRSMG9yVUVOME9USjNjaXR2UVEiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "jFPJFC-2eRyBw7Sl0wyEBhsdvRZtKk8hc6HykEPAiofZlIwdIu76u2xHqMVZWSZdpxwMNUnnawTEAqgMWFydMA"}\' > .well-known/acme-challenge/ZXZhR3hmQURzNnBTUmIyTEF2OUlaZjE3RHQzanV4R0orUEN0OTJ3citvQQ
# run only once per server:
$(command -v python2 || command -v python2.7 || command -v python2.6) -c \\
"import BaseHTTPServer, SimpleHTTPServer; \\
SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map = {\'\': \'application/jose+json\'}; \\
s = BaseHTTPServer.HTTPServer((\'\', 4430), SimpleHTTPServer.SimpleHTTPRequestHandler); \\
s.serve_forever()" \n""")
        #self.assertTrue(validation in message)

        mock_verify.return_value = False
        self.assertEqual([None], self.auth.perform(self.achalls))