Пример #1
0
    def _convert_p4exception_to_scmexception(e):
        error = str(e)

        if 'Perforce password' in error or 'Password must be set' in error:
            raise AuthenticationError(msg=error)
        elif 'SSL library must be at least version' in error:
            raise SCMError('The specified Perforce port includes ssl:, but '
                           'the p4python library was built without SSL '
                           'support or the system library path is incorrect. ')
        elif ('check $P4PORT' in error
              or (error.startswith('[P4.connect()] TCP connect to')
                  and 'failed.' in error)):
            raise RepositoryNotFoundError
        elif "To allow connection use the 'p4 trust' command" in error:
            fingerprint = error.split('\\n')[3]
            raise UnverifiedCertificateError(
                Certificate(fingerprint=fingerprint))
        else:
            raise SCMError(error)
Пример #2
0
    def on_ssl_failure(e, path, cert_data):
        logging.error('SVN: Failed to get repository information '
                      'for %s: %s' % (path, e))

        error = SVNTool.normalize_error(e)

        if isinstance(error, AuthenticationError):
            raise error

        if cert_data:
            failures = cert_data['failures']

            reasons = []

            if failures & SVNCertificateFailures.NOT_YET_VALID:
                reasons.append(_('The certificate is not yet valid.'))

            if failures & SVNCertificateFailures.EXPIRED:
                reasons.append(_('The certificate has expired.'))

            if failures & SVNCertificateFailures.CN_MISMATCH:
                reasons.append(_('The certificate hostname does not '
                                 'match.'))

            if failures & SVNCertificateFailures.UNKNOWN_CA:
                reasons.append(
                    _('The certificate is not issued by a '
                      'trusted authority. Use the fingerprint '
                      'to validate the certificate manually.'))

            raise UnverifiedCertificateError(
                Certificate(valid_from=cert_data['valid_from'],
                            valid_until=cert_data['valid_until'],
                            hostname=cert_data['hostname'],
                            realm=cert_data['realm'],
                            fingerprint=cert_data['finger_print'],
                            issuer=cert_data['issuer_dname'],
                            failures=reasons))

        raise RepositoryNotFoundError()
Пример #3
0
    def check_repository(cls, path, username=None, password=None,
                         local_site_name=None):
        """
        Performs checks on a repository to test its validity.

        This should check if a repository exists and can be connected to.
        This will also check if the repository requires an HTTPS certificate.

        The result is returned as an exception. The exception may contain
        extra information, such as a human-readable description of the problem.
        If the repository is valid and can be connected to, no exception
        will be thrown.
        """
        super(SVNTool, cls).check_repository(path, username, password,
                                             local_site_name)

        cert_data = {}

        def ssl_server_trust_prompt(trust_dict):
            cert_data.update(trust_dict)
            return False, 0, False

        config_dir, client = cls.build_client(username, password,
                                              local_site_name)
        client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt

        try:
            info = client.info2(path, recurse=False)
            logging.debug('SVN: Got repository information for %s: %s' %
                          (path, info))
        except ClientError, e:
            logging.error('SVN: Failed to get repository information '
                          'for %s: %s' % (path, e))

            if 'callback_get_login required' in str(e):
                raise AuthenticationError(msg="Authentication failed")

            if cert_data:
                failures = cert_data['failures']

                reasons = []

                if failures & SVNCertificateFailures.NOT_YET_VALID:
                    reasons.append(_('The certificate is not yet valid.'))

                if failures & SVNCertificateFailures.EXPIRED:
                    reasons.append(_('The certificate has expired.'))

                if failures & SVNCertificateFailures.CN_MISMATCH:
                    reasons.append(_('The certificate hostname does not '
                                     'match.'))

                if failures & SVNCertificateFailures.UNKNOWN_CA:
                    reasons.append(_('The certificate is not issued by a '
                                     'trusted authority. Use the fingerprint '
                                     'to validate the certificate manually.'))

                raise UnverifiedCertificateError(
                    Certificate(valid_from=cert_data['valid_from'],
                                valid_until=cert_data['valid_until'],
                                hostname=cert_data['hostname'],
                                realm=cert_data['realm'],
                                fingerprint=cert_data['finger_print'],
                                issuer=cert_data['issuer_dname'],
                                failures=reasons))

            raise RepositoryNotFoundError()
Пример #4
0
    def run_worker(self):
        """Run a Perforce command from within a Perforce connection context.

        This will set up a Perforce connection for an operation, disconnecting
        when the context is finished, and raising a suitable exception if
        anything goes wrong.

        Context:
            The context for the connection. Once the context ends, the
            connection will close.

            No variables are passed to the context.

        Raises:
            reviewboard.scmtools.errors.AuthenticationError:
                There was an error authenticating with Perforce. Credentials
                may be incorrect. The exception message will have more details.

            reviewboard.scmtools.errors.RepositoryNotFoundError:
                The repository this was attempting to use could not be found.

            reviewboard.scmtools.errors.SCMError:
                There was a general error with talking to the repository or
                executing a command. The exception message will have more
                details.

            reviewboard.scmtools.errors.UnverifiedCertificateError:
                The SSL certificate for the Perforce server could not be
                verified. It may be self-signed. The certificate information
                will be available in the exception.

        Example:
            .. code-block:: python

                with client.run_worker():
                    ...
        """
        from P4 import P4Exception

        try:
            with self.connect():
                yield
        except P4Exception as e:
            error = six.text_type(e)

            if 'Perforce password' in error or 'Password must be set' in error:
                raise AuthenticationError(msg=error)
            elif 'SSL library must be at least version' in error:
                raise SCMError(
                    _('The specified Perforce port includes ssl:, but the '
                      'p4python library was built without SSL support or the '
                      'system library path is incorrect.'))
            elif ('check $P4PORT' in error
                  or (error.startswith('[P4.connect()] TCP connect to')
                      and 'failed.' in error)):
                raise RepositoryNotFoundError
            elif "To allow connection use the 'p4 trust' command" in error:
                fingerprint = error.split(r'\n')[3]

                raise UnverifiedCertificateError(
                    Certificate(fingerprint=fingerprint))
            else:
                raise SCMError(error)
Пример #5
0
    def http_request(self,
                     url,
                     body=None,
                     headers=None,
                     method='GET',
                     username=None,
                     password=None):
        """Perform some HTTP operation on a given URL.

        If the ``username`` and ``password`` arguments are provided, the
        headers required for HTTP Basic Authentication will be added to
        the request.

        Args:
            url (unicode):
                The URL to open.

            body (unicode, optional):
                The request body.

            headers (dict, optional):
                Headers to include in the request.

            method (unicode, optional):
                The HTTP method to use to perform the request.

            username (unicode, optional):
                The username to use for HTTP Basic Authentication.

            password (unicode, optional):
                The password to use for HTTP Basic Authentication.

        Returns:
            tuple:
            A tuple of:

            * The response body (:py:class:`bytes`)
            * The response headers (:py:class:`dict`)

        Raises:
            urllib2.HTTPError:
                When the HTTP request fails.

            urllib2.URLError:
                When there is an error communicating with the URL.
        """
        request = URLRequest(url, body, headers, method=method)

        if username is not None and password is not None:
            request.add_basic_auth(username, password)

        try:
            if (self.hosting_service
                    and 'ssl_cert' in self.hosting_service.account.data):
                # create_default_context only exists in Python 2.7.9+. Using it
                # here should be fine, however, because accepting invalid or
                # self-signed certificates is only possible when running
                # against versions that have this (see the check for
                # create_default_context below).
                context = ssl.create_default_context()
                context.load_verify_locations(
                    cadata=self.hosting_service.account.data['ssl_cert'])
                context.check_hostname = False
            else:
                context = None

            response = urlopen(request, context=context)
            return response.read(), response.headers
        except URLError as e:
            if ('CERTIFICATE_VERIFY_FAILED' not in six.text_type(e)
                    or not hasattr(ssl, 'create_default_context')):
                raise

            parts = urlparse(url)
            port = parts.port or 443

            cert_pem = ssl.get_server_certificate((parts.hostname, port))
            cert_der = ssl.PEM_cert_to_DER_cert(cert_pem)

            cert = x509.load_pem_x509_certificate(cert_pem.encode('ascii'),
                                                  default_backend())
            issuer = cert.issuer.get_attributes_for_oid(
                x509.oid.NameOID.COMMON_NAME)[0].value
            subject = cert.subject.get_attributes_for_oid(
                x509.oid.NameOID.COMMON_NAME)[0].value

            raise UnverifiedCertificateError(
                Certificate(pem_data=cert_pem,
                            valid_from=cert.not_valid_before.isoformat(),
                            valid_until=cert.not_valid_after.isoformat(),
                            issuer=issuer,
                            hostname=subject,
                            fingerprint=hashlib.sha256(cert_der).hexdigest()))