def test_post_with_unknown_cert(self): """Testing the POST repositories/ API with Unknown Certificate error""" class Certificate(object): failures = ['failures'] fingerprint = 'fingerprint' hostname = 'example.com' issuer = 'issuer' valid_from = 'valid_from' valid_until = 'valid_until' cert = Certificate() self.spy_on(TestTool.check_repository, owner=TestTool, op=kgb.SpyOpRaise(UnverifiedCertificateError(cert))) rsp = self._post_repository(expected_status=403) self.assertEqual(rsp['stat'], 'fail') self.assertEqual(rsp['err']['code'], UNVERIFIED_HOST_CERT.code) self.assertIn('certificate', rsp) self.assertEqual(rsp['certificate']['failures'], cert.failures) self.assertEqual(rsp['certificate']['fingerprint'], cert.fingerprint) self.assertEqual(rsp['certificate']['hostname'], cert.hostname) self.assertEqual(rsp['certificate']['issuer'], cert.issuer) self.assertEqual(rsp['certificate']['valid']['from'], cert.valid_from) self.assertEqual(rsp['certificate']['valid']['until'], cert.valid_until)
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)
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()
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()
def _check_repository(cls, *args, **kwargs): if not saw['accept_certificate']: raise UnverifiedCertificateError(cert)
def _check_repository(cls, *args, **kwargs): raise UnverifiedCertificateError(cert)
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)
def _check_repository(cls, *args, **kwargs): if not TestTool.accept_certificate.called: raise UnverifiedCertificateError(cert)
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()))