Esempio n. 1
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.
        """
        # CVS paths are a bit strange, so we can't actually use the
        # SSH checking in SCMTool.check_repository. Do our own.
        m = cls.ext_cvsroot_re.match(path)

        if m:
            try:
                sshutils.check_host(m.group('hostname'), username, password,
                                    local_site_name)
            except SSHAuthenticationError, e:
                # Represent an SSHAuthenticationError as a standard
                # AuthenticationError.
                raise AuthenticationError(e.allowed_types, unicode(e),
                                          e.user_key)
            except:
Esempio n. 2
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.
        """
        if sshutils.is_ssh_uri(path):
            username, hostname = SCMTool.get_auth_from_uri(path, username)
            logging.debug(
                "%s: Attempting ssh connection with host: %s, username: %s" %
                (cls.__name__, hostname, username))

            try:
                sshutils.check_host(hostname, username, password,
                                    local_site_name)
            except SSHAuthenticationError as e:
                # Represent an SSHAuthenticationError as a standard
                # AuthenticationError.
                raise AuthenticationError(e.allowed_types, six.text_type(e),
                                          e.user_key)
            except:
                # Re-raise anything else
                raise
Esempio n. 3
0
    def _do_on_path(self, cb, path, revision=HEAD):
        if not path:
            raise FileNotFoundError(path, revision)

        try:
            normpath = self.__normalize_path(path)

            # SVN expects to have URLs escaped. Take care to only
            # escape the path part of the URL.
            if self.client.is_url(normpath):
                pathtuple = urlparse.urlsplit(normpath)
                path = pathtuple[2]
                if isinstance(path, unicode):
                    path = path.encode('utf-8', 'ignore')
                normpath = urlparse.urlunsplit(
                    (pathtuple[0], pathtuple[1], urllib.quote(path), '', ''))

            normrev = self.__normalize_revision(revision)
            return cb(normpath, normrev)

        except ClientError, e:
            stre = str(e)
            if 'File not found' in stre or 'path not found' in stre:
                raise FileNotFoundError(path, revision, detail=str(e))
            elif 'callback_ssl_server_trust_prompt required' in stre:
                raise SCMError(
                    'HTTPS certificate not accepted.  Please ensure that '
                    'the proper certificate exists in %s '
                    'for the user that reviewboard is running as.' %
                    os.path.join(self.config_dir, 'auth'))
            elif 'callback_get_login required' in stre:
                raise AuthenticationError(
                    msg='Login to the SCM server failed.')
            else:
                raise SCMError(e)
Esempio n. 4
0
 def normalize_error(cls, e):
     if 'callback_get_login required' in six.text_type(e):
         return AuthenticationError(
             msg='Authentication failed when talking to the Subversion '
             'repository')
     else:
         return SCMError(e)
Esempio n. 5
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 'check $P4PORT' in error:
         raise RepositoryNotFoundError
     else:
         raise SCMError(error)
Esempio n. 6
0
    def test_post_with_authentication_error(self):
        """Testing the POST repositories/ API with Authentication Error"""
        self.spy_on(
            TestTool.check_repository,
            owner=TestTool,
            op=kgb.SpyOpRaise(AuthenticationError()))

        rsp = self._post_repository(expected_status=403)

        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], REPO_AUTHENTICATION_ERROR.code)
        self.assertIn('reason', rsp)
Esempio n. 7
0
    def test_post_with_missing_user_key(self):
        """Testing the POST repositories/ API with Missing User Key error"""
        self.spy_on(
            TestTool.check_repository,
            owner=TestTool,
            op=kgb.SpyOpRaise(AuthenticationError(allowed_types=['publickey'],
                                                  user_key=None)))

        rsp = self._post_repository(expected_status=403)

        self.assertEqual(rsp['stat'], 'fail')
        self.assertEqual(rsp['err']['code'], MISSING_USER_KEY.code)
Esempio n. 8
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.
        """
        try:
            cvsroot, repopath = cls.build_cvsroot(path, username, password)
        except ValidationError as e:
            raise SCMError('; '.join(e.messages))

        # CVS paths are a bit strange, so we can't actually use the
        # SSH checking in SCMTool.check_repository. Do our own.
        m = cls.remote_cvsroot_re.match(path)

        if m and m.group('protocol') in ('ext', 'ssh', 'extssh'):
            try:
                sshutils.check_host(m.group('hostname'), username, password,
                                    local_site_name)
            except SSHAuthenticationError as e:
                # Represent an SSHAuthenticationError as a standard
                # AuthenticationError.
                raise AuthenticationError(e.allowed_types, six.text_type(e),
                                          e.user_key)
            except:
                # Re-raise anything else
                raise

        client = CVSClient(cvsroot, repopath, local_site_name)

        try:
            client.check_repository()
        except (AuthenticationError, SCMError):
            raise
        except (SSHError, FileNotFoundError):
            raise RepositoryNotFoundError()
Esempio n. 9
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)
Esempio n. 10
0
    def on_ssl_failure(e, path, cert_data):
        logging.error('SVN: Failed to get repository information '
                      'for %s: %s' % (path, e))

        if 'callback_get_login required' in six.text_type(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()
Esempio n. 11
0
    def check_repository(self):
        # Running 'cvs version' and specifying a CVSROOT will bail out if said
        # CVSROOT is invalid, which is perfect for us. This used to use
        # 'cvs rls' which is maybe slightly more correct, but rls is only
        # available in CVS 1.12+
        p = SCMTool.popen(['cvs', '-f', '-d', self.cvsroot, 'version'],
                          self.local_site_name)
        errmsg = six.text_type(p.stderr.read())

        if p.wait() != 0:
            logging.error(
                'CVS repository validation failed for '
                'CVSROOT %s: %s', self.cvsroot, errmsg)

            auth_failed_prefix = 'cvs version: authorization failed: '

            # See if there's an "authorization failed" anywhere in here. If so,
            # we want to raise AuthenticationError with that error message.
            for line in errmsg.splitlines():
                if line.startswith(auth_failed_prefix):
                    raise AuthenticationError(
                        msg=line[len(auth_failed_prefix):].strip())

            raise SCMError(errmsg)
Esempio n. 12
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)
Esempio n. 13
0
    try:
        client.connect(hostname, username=username, password=password)
    except paramiko.BadHostKeyException, e:
        raise BadHostKeyError(e.hostname, e.key, e.expected_key)
    except paramiko.AuthenticationException, e:
        # Some AuthenticationException instances have allowed_types set,
        # and some don't.
        allowed_types = getattr(e, 'allowed_types', [])

        if 'publickey' in allowed_types:
            key = get_user_key()
        else:
            key = None

        raise AuthenticationError(allowed_types, key)
    except paramiko.SSHException, e:
        raise SCMError(unicode(e))


def register_rbssh(envvar):
    """Registers rbssh in an environment variable.

    This is a convenience method for making sure that rbssh is set properly
    in the environment for different tools. In some cases, we need to
    specifically place it in the system environment using ``os.putenv``,
    while in others (Mercurial, Bazaar), we need to place it in ``os.environ``.
    """
    os.putenv(envvar, 'rbssh')
    os.environ[envvar] = 'rbssh'
Esempio n. 14
0
    def check_repository(cls,
                         path,
                         username=None,
                         password=None,
                         local_site_name=None):
        """Check a repository configuration for 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, if the repository configuration is invalid, is returned as
        an exception. The exception may contain extra information, such as a
        human-readable description of the problem. Many types of errors can
        be returned, based on issues with the repository, authentication,
        HTTPS certificate, or SSH keys.

        If the repository configuration is valid and a connection can be
        established, this will simply return.

        Subclasses should override this to provide more specific validation
        logic.

        Args:
            path (unicode):
                The repository path.

            username (unicode, optional):
                The optional username for the repository.

            password (unicode, optional):
                The optional password for the repository.

            local_site_name (unicode, optional):
                The name of the Local Site that owns this repository. This is
                optional.

        Raises:
            reviewboard.scmtools.errors.AuthenticationError:
                The provided username/password or the configured SSH key could
                not be used to authenticate with the repository.

            reviewboard.scmtools.errors.RepositoryNotFoundError:
                A repository could not be found at the given path.

            reviewboard.scmtools.errors.SCMError:
                There was a generic error with the repository or its
                configuration.  Details will be provided in the error message.

            reviewboard.scmtools.errors.UnverifiedCertificateError:
                The SSL certificate on the server could not be verified.
                Information on the certificate will be returned in order to
                allow verification and acceptance using
                :py:meth:`accept_certificate`.

            reviewboard.ssh.errors.BadHostKeyError:
                An SSH path was provided, but the host key for the repository
                did not match the expected key.

            reviewboard.ssh.errors.SSHError:
                An SSH path was provided, but there was an error establishing
                the SSH connection.

            reviewboard.ssh.errors.SSHInvalidPortError:
                An SSH path was provided, but the port specified was not a
                valid number.

            Exception:
                An unexpected exception has ocurred. Callers should check
                for this and handle it.
        """
        if sshutils.is_ssh_uri(path):
            username, hostname = SCMTool.get_auth_from_uri(path, username)
            logging.debug(
                "%s: Attempting ssh connection with host: %s, username: %s" %
                (cls.__name__, hostname, username))

            try:
                sshutils.check_host(hostname, username, password,
                                    local_site_name)
            except SSHAuthenticationError as e:
                # Represent an SSHAuthenticationError as a standard
                # AuthenticationError.
                raise AuthenticationError(e.allowed_types, six.text_type(e),
                                          e.user_key)
            except:
                # Re-raise anything else
                raise
Esempio n. 15
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()
Esempio n. 16
0
                       password=password,
                       pkey=get_user_key(local_site_name),
                       **kwargs)
    except paramiko.BadHostKeyException, e:
        raise BadHostKeyError(e.hostname, e.key, e.expected_key)
    except paramiko.AuthenticationException, e:
        # Some AuthenticationException instances have allowed_types set,
        # and some don't.
        allowed_types = getattr(e, 'allowed_types', [])

        if 'publickey' in allowed_types:
            key = get_user_key(local_site_name)
        else:
            key = None

        raise AuthenticationError(allowed_types=allowed_types, user_key=key)
    except paramiko.SSHException, e:
        if str(e) == 'No authentication methods available':
            raise AuthenticationError
        else:
            raise SCMError(unicode(e))


def register_rbssh(envvar):
    """Registers rbssh in an environment variable.

    This is a convenience method for making sure that rbssh is set properly
    in the environment for different tools. In some cases, we need to
    specifically place it in the system environment using ``os.putenv``,
    while in others (Mercurial, Bazaar), we need to place it in ``os.environ``.
    """
Esempio n. 17
0
 def _check_repository(cls, *args, **kwargs):
     raise AuthenticationError(allowed_types=['publickey'],
                               user_key=None)