예제 #1
0
파일: client.py 프로젝트: twisted/txacme
    def _add_nonce(self, response):
        """
        Store a nonce from a response we received.

        :param twisted.web.iweb.IResponse response: The HTTP response.

        :return: The response, unmodified.
        """
        nonce = response.headers.getRawHeaders(REPLAY_NONCE_HEADER, [None])[0]
        with LOG_JWS_ADD_NONCE(raw_nonce=nonce) as action:
            if nonce is None:
                return _fail_and_consume(
                    response,
                    errors.ClientError(str(errors.MissingNonce(response))),
                )
            else:
                try:
                    decoded_nonce = Header._fields['nonce'].decode(
                        nonce.decode('ascii'))
                    action.add_success_fields(nonce=decoded_nonce)
                except DeserializationError as error:
                    return _fail_and_consume(response,
                                             errors.BadNonce(nonce, error))
                self._nonces.add(decoded_nonce)
                return response
예제 #2
0
파일: client.py 프로젝트: kgw4it/certbot
    def answer_challenge(self, challb, response):
        """Answer challenge.

        :param challb: Challenge Resource body.
        :type challb: `.ChallengeBody`

        :param response: Corresponding Challenge response
        :type response: `.challenges.ChallengeResponse`

        :returns: Challenge Resource with updated body.
        :rtype: `.ChallengeResource`

        :raises .UnexpectedUpdate:

        """
        response = self._post(challb.uri, response)
        try:
            authzr_uri = response.links['up']['url']
        except KeyError:
            raise errors.ClientError('"up" Link header missing')
        challr = messages.ChallengeResource(
            authzr_uri=authzr_uri,
            body=messages.ChallengeBody.from_json(response.json()))
        # TODO: check that challr.uri == response.headers['Location']?
        if challr.uri != challb.uri:
            raise errors.UnexpectedUpdate(challr.uri)
        return challr
예제 #3
0
파일: client.py 프로젝트: jerith/txacme
    def fetch_chain(self, certr, max_length=10):
        """
        Fetch the intermediary chain for a certificate.

        :param acme.messages.CertificateResource certr: The certificate to
            fetch the chain for.
        :param int max_length: The maximum length of the chain that will be
            fetched.

        :rtype: Deferred[List[`acme.messages.CertificateResource`]]
        :return: The issuer certificate chain, ordered with the trust anchor
                 last.
        """
        action = LOG_ACME_FETCH_CHAIN()
        with action.context():
            if certr.cert_chain_uri is None:
                return succeed([])
            elif max_length < 1:
                raise errors.ClientError('chain too long')
            return (
                DeferredContext(
                    self._client.get(
                        certr.cert_chain_uri,
                        content_type=DER_CONTENT_TYPE,
                        headers=Headers({b'Accept': [DER_CONTENT_TYPE]})))
                .addCallback(self._parse_certificate)
                .addCallback(
                    lambda issuer:
                    self.fetch_chain(issuer, max_length=max_length - 1)
                    .addCallback(lambda chain: [issuer] + chain))
                .addActionFinish())
예제 #4
0
파일: client.py 프로젝트: twisted/txacme
        def cb_extract_new_nonce(directory):
            try:
                self._new_nonce = directory.newNonce
            except AttributeError:
                raise errors.ClientError('Directory has no newNonce URL',
                                         directory)

            return directory
예제 #5
0
 def _expect_response(cls, response, code):
     """
     Ensure we got the expected response code.
     """
     if response.code != code:
         raise errors.ClientError(
             'Expected {!r} response but got {!r}'.format(
                 code, response.code))
     return response
예제 #6
0
파일: client.py 프로젝트: twisted/txacme
 def _got_json(jobj):
     if 400 <= response.code < 600:
         if (response_ct.lower().startswith(JSON_ERROR_CONTENT_TYPE)
                 and jobj is not None):
             raise ServerError(messages.Error.from_json(jobj), response)
         else:
             # response is not JSON object
             return _fail_and_consume(
                 response, errors.ClientError('Response is not JSON.'))
     elif content_type not in response_ct.lower():
         return _fail_and_consume(
             response,
             errors.ClientError(
                 'Unexpected response Content-Type: {0!r}. '
                 'Expecting {1!r}.'.format(response_ct, content_type)))
     elif JSON_CONTENT_TYPE in content_type.lower() and jobj is None:
         return _fail_and_consume(
             response, errors.ClientError('Missing JSON body.'))
     return response
예제 #7
0
파일: client.py 프로젝트: twisted/txacme
 def _expect_response(cls, response, codes):
     """
     Ensure we got one of the expected response codes`.
     """
     if response.code not in codes:
         return _fail_and_consume(
             response,
             errors.ClientError(
                 'Expected {!r} response but got {!r}'.format(
                     codes, response.code)))
     return response
예제 #8
0
 def _parse_challenge(cls, response):
     """
     Parse a challenge resource.
     """
     links = _parse_header_links(response)
     try:
         authzr_uri = links['up']['url']
     except KeyError:
         raise errors.ClientError('"up" link missing')
     return (response.json().addCallback(
         lambda body: messages.ChallengeResource(authzr_uri=authzr_uri,
                                                 body=messages.ChallengeBody
                                                 .from_json(body))))
예제 #9
0
    def revoke(self, cert):
        """Revoke certificate.

        :param .ComparableX509 cert: `OpenSSL.crypto.X509` wrapped in
            `.ComparableX509`

        :raises .ClientError: If revocation is unsuccessful.

        """
        response = self.net.post(messages.Revocation.url(self.new_reg_uri),
                                 messages.Revocation(certificate=cert))
        if response.status_code != http_client.OK:
            raise errors.ClientError(
                'Successful revocation must return HTTP OK status')
예제 #10
0
 def _parse_authorization(cls, response, uri=None):
     """
     Parse an authorization resource.
     """
     links = _parse_header_links(response)
     try:
         new_cert_uri = links[u'next'][u'url']
     except KeyError:
         raise errors.ClientError('"next" link missing')
     return (response.json().addCallback(
         lambda body: messages.AuthorizationResource(
             body=messages.Authorization.from_json(body),
             uri=cls._maybe_location(response, uri=uri),
             new_cert_uri=new_cert_uri)))
예제 #11
0
    def request_issuance(self, csr, authzrs):
	print("Se ejecuta request issuance")
        """Request issuance.

        :param csr: CSR
        :type csr: `OpenSSL.crypto.X509Req` wrapped in `.ComparableX509`

        :param authzrs: `list` of `.AuthorizationResource`

        :returns: Issued certificate
        :rtype: `.messages.CertificateResource`

        """
        assert authzrs, "Authorizations list is empty"
        logger.debug("Requesting issuance...")
        # TODO: assert len(authzrs) == number of SANs

	#Checks if STARValidityCertbot file containing recurrent_cert_validity exists
	if os.path.isfile("../../STARValidityCertbot"):
		print "CLIENT.PY: STARValidityCertbot does exist"
		fileSTAR = open("../../STARValidityCertbot", "r")
		recurrent = True
		recurrent_cert_validity = int(float(fileSTAR.read()))  
	        req = messages.CertificateRequest(csr=csr, recurrent=recurrent,recurrent_cert_validity=recurrent_cert_validity)
	else:
		print "CLIENT.PY: STARValidityCertbot does NOT exist"
		req = messages.CertificateRequest(csr=csr)
	print "CSR sent to server is %s" % req 
        content_type = DER_CONTENT_TYPE  # TODO: add 'cert_type 'argument
        response = self.net.post(
            self.directory.new_cert,
            req,
            content_type=content_type,
            headers={'Accept': content_type})

        cert_chain_uri = response.links.get('up', {}).get('url')

        try:
            uri = response.headers['Location']
	    file=open('/root/certId','wr+')
	    file.write(uri)
	    print(uri)
        except KeyError:
            raise errors.ClientError('"Location" Header missing')

        return messages.CertificateResource(
            uri=uri, authzrs=authzrs, cert_chain_uri=cert_chain_uri,
            body=jose.ComparableX509(OpenSSL.crypto.load_certificate(
                OpenSSL.crypto.FILETYPE_ASN1, response.content)))
예제 #12
0
    def _regr_from_response(cls, response, uri=None, new_authzr_uri=None,
                            terms_of_service=None):
        if 'terms-of-service' in response.links:
            terms_of_service = response.links['terms-of-service']['url']
        if 'next' in response.links:
            new_authzr_uri = response.links['next']['url']

        if new_authzr_uri is None:
            raise errors.ClientError('"next" link missing')

        return messages.RegistrationResource(
            body=messages.Registration.from_json(response.json()),
            uri=response.headers.get('Location', uri),
            new_authzr_uri=new_authzr_uri,
            terms_of_service=terms_of_service)
예제 #13
0
    def _authzr_from_response(self, response, identifier,
                              uri=None, new_cert_uri=None):
        # pylint: disable=no-self-use
        if new_cert_uri is None:
            try:
                new_cert_uri = response.links['next']['url']
            except KeyError:
                raise errors.ClientError('"next" link missing')

        authzr = messages.AuthorizationResource(
            body=messages.Authorization.from_json(response.json()),
            uri=response.headers.get('Location', uri),
            new_cert_uri=new_cert_uri)
        if authzr.body.identifier != identifier:
            raise errors.UnexpectedUpdate(authzr)
        return authzr
예제 #14
0
파일: client.py 프로젝트: twisted/txacme
    def _parse_challenge(cls, response):
        """
        Parse a challenge resource.
        """
        links = _parse_header_links(response)
        try:
            authzr_uri = links['up']['url']
        except KeyError:
            yield _fail_and_consume(response,
                                    errors.ClientError('"up" link missing'))

        body = yield response.json()
        defer.returnValue(
            messages.ChallengeResource(
                authzr_uri=authzr_uri,
                body=messages.ChallengeBody.from_json(body),
            ))
예제 #15
0
    def _get(self, uri, content_type=JSON_CONTENT_TYPE, **kwargs):
        """Send GET request.

        :raises .ClientError:

        :returns: HTTP Response
        :rtype: `requests.Response`

        """
        logger.debug('Sending GET request to %s', uri)
        kwargs.setdefault('verify', self.verify_ssl)
        try:
            response = requests.get(uri, **kwargs)
        except requests.exceptions.RequestException as error:
            raise errors.ClientError(error)
        self._check_response(response, content_type=content_type)
        return response
예제 #16
0
    def answer_challenge(self, challb, response):
        """Answer challenge.

        :param challb: Challenge Resource body.
        :type challb: `.ChallengeBody`

        :param response: Corresponding Challenge response
        :type response: `.challenges.ChallengeResponse`

        :returns: Challenge Resource with updated body.
        :rtype: `.ChallengeResource`

        :raises .UnexpectedUpdate:

        """
        # Because sending keyAuthorization in a response challenge has been removed from the ACME
        # spec, it is not included in the KeyAuthorizationResponseChallenge JSON by default.
        # However as a migration path, we temporarily expect a malformed error from the server,
        # and fallback by resending the challenge response with the keyAuthorization field.
        # TODO: Remove this fallback for Certbot 0.34.0
        try:
            response = self._post(challb.uri, response)
        except messages.Error as error:
            if (error.code == 'malformed' and isinstance(
                    response, challenges.KeyAuthorizationChallengeResponse)):
                logger.debug(
                    'Error while responding to a challenge without keyAuthorization '
                    'in the JWS, your ACME CA server may not support it:\n%s',
                    error)
                logger.debug('Retrying request with keyAuthorization set.')
                response._dump_authorization_key(True)  # pylint: disable=protected-access
                response = self._post(challb.uri, response)
            else:
                raise
        try:
            authzr_uri = response.links['up']['url']
        except KeyError:
            raise errors.ClientError('"up" Link header missing')
        challr = messages.ChallengeResource(
            authzr_uri=authzr_uri,
            body=messages.ChallengeBody.from_json(response.json()))
        # TODO: check that challr.uri == response.headers['Location']?
        if challr.uri != challb.uri:
            raise errors.UnexpectedUpdate(challr.uri)
        return challr
예제 #17
0
    def check_cert(self, certr):
        """Check for new cert.

        :param certr: Certificate Resource
        :type certr: `.CertificateResource`

        :returns: Updated Certificate Resource.
        :rtype: `.CertificateResource`

        """
        # TODO: acme-spec 5.1 table action should be renamed to
        # "refresh cert", and this method integrated with self.refresh
        response, cert = self._get_cert(certr.uri)
        if 'Location' not in response.headers:
            raise errors.ClientError('Location header missing')
        if response.headers['Location'] != certr.uri:
            raise errors.UnexpectedUpdate(response.text)
        return certr.update(body=cert)
예제 #18
0
    def _revoke(self, cert, rsn, url):
        """Revoke certificate.

        :param .ComparableX509 cert: `OpenSSL.crypto.X509` wrapped in
            `.ComparableX509`

        :param int rsn: Reason code for certificate revocation.

        :param str url: ACME URL to post to

        :raises .ClientError: If revocation is unsuccessful.

        """
        response = self._post(
            url, messages.Revocation(certificate=cert, reason=rsn))
        if response.status_code != http_client.OK:
            raise errors.ClientError(
                'Successful revocation must return HTTP OK status')
    def revoke(self, cert, rsn):
        """Revoke certificate.

        :param .ComparableX509 cert: `OpenSSL.crypto.X509` wrapped in
            `.ComparableX509`

        :param int rsn: Reason code for certificate revocation.

        :raises .ClientError: If revocation is unsuccessful.

        """
        response = self.net.post(self.directory[messages.Revocation],
                                 messages.Revocation(certificate=cert,
                                                     reason=rsn),
                                 content_type=None)
        if response.status_code != http_client.OK:
            raise errors.ClientError(
                'Successful revocation must return HTTP OK status')
예제 #20
0
 def _parse_regr_response(self,
                          response,
                          uri=None,
                          new_authzr_uri=None,
                          terms_of_service=None):
     """
     Parse a registration response from the server.
     """
     links = _parse_header_links(response)
     if u'terms-of-service' in links:
         terms_of_service = links[u'terms-of-service'][u'url']
     if u'next' in links:
         new_authzr_uri = links[u'next'][u'url']
     if new_authzr_uri is None:
         raise errors.ClientError('"next" link missing')
     return (response.json().addCallback(
         lambda body: messages.RegistrationResource(
             body=messages.Registration.from_json(body),
             uri=self._maybe_location(response, uri=uri),
             new_authzr_uri=new_authzr_uri,
             terms_of_service=terms_of_service)))
예제 #21
0
    def request_issuance(self, csr, authzrs):
        """Request issuance.

        :param csr: CSR
        :type csr: `OpenSSL.crypto.X509Req` wrapped in `.ComparableX509`

        :param authzrs: `list` of `.AuthorizationResource`

        :returns: Issued certificate
        :rtype: `.messages.CertificateResource`

        """
        assert authzrs, "Authorizations list is empty"
        logger.debug("Requesting issuance...")

        # TODO: assert len(authzrs) == number of SANs
        req = messages.CertificateRequest(
            csr=csr, authorizations=tuple(authzr.uri for authzr in authzrs))

        content_type = self.DER_CONTENT_TYPE  # TODO: add 'cert_type 'argument
        response = self.net.post(
            authzrs[0].new_cert_uri,  # TODO: acme-spec #90
            req,
            content_type=content_type,
            headers={'Accept': content_type})

        cert_chain_uri = response.links.get('up', {}).get('url')

        try:
            uri = response.headers['Location']
        except KeyError:
            raise errors.ClientError('"Location" Header missing')

        return messages.CertificateResource(
            uri=uri,
            authzrs=authzrs,
            cert_chain_uri=cert_chain_uri,
            body=jose.ComparableX509(
                OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
                                                response.content)))
예제 #22
0
    def _post(self, uri, obj, content_type=JSON_CONTENT_TYPE, **kwargs):
        """Send POST data.

        :param JSONDeSerializable obj: Will be wrapped in JWS.
        :param str content_type: Expected ``Content-Type``, fails if not set.

        :raises acme.messages.ClientError:

        :returns: HTTP Response
        :rtype: `requests.Response`

        """
        data = self._wrap_in_jws(obj, self._get_nonce(uri))
        logger.debug('Sending POST data to %s: %s', uri, data)
        kwargs.setdefault('verify', self.verify_ssl)
        try:
            response = requests.post(uri, data=data, **kwargs)
        except requests.exceptions.RequestException as error:
            raise errors.ClientError(error)

        self._add_nonce(response)
        self._check_response(response, content_type=content_type)
        return response
예제 #23
0
 def test_revocation_error(self):
     from acme import errors as acme_errors
     self.mock_acme_client.side_effect = acme_errors.ClientError()
     self.assertRaises(acme_errors.ClientError, self._call)
     self.mock_success_revoke.assert_not_called()