diff options
Diffstat (limited to 'debian/python-leap.common/usr/share')
27 files changed, 0 insertions, 4077 deletions
| diff --git a/debian/python-leap.common/usr/share/doc/python-leap.common/changelog.Debian.gz b/debian/python-leap.common/usr/share/doc/python-leap.common/changelog.Debian.gzBinary files differ deleted file mode 100644 index 9261f57..0000000 --- a/debian/python-leap.common/usr/share/doc/python-leap.common/changelog.Debian.gz +++ /dev/null diff --git a/debian/python-leap.common/usr/share/doc/python-leap.common/copyright b/debian/python-leap.common/usr/share/doc/python-leap.common/copyright deleted file mode 100644 index a132a29..0000000 --- a/debian/python-leap.common/usr/share/doc/python-leap.common/copyright +++ /dev/null @@ -1,16 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: leap-common -Upstream-Contact: kali@leap.se -Source: <git://code.leap.se/leap_pycommon/> - -Files: * -    Copyright (C) 2013 LEAP -License: GPL-3+ - -Files: debian/* -Copyright: Copyright 2013 Micah Anderson <micah@leap.se> -License: GPL-3+ -  -License: GPL-3+ - On Debian systems, the complete text of the GNU General - Public License can be found in `/usr/share/common-licenses/GPL'. diff --git a/debian/python-leap.common/usr/share/pyshared/leap.common-0.2.3_dev-nspkg.pth b/debian/python-leap.common/usr/share/pyshared/leap.common-0.2.3_dev-nspkg.pth deleted file mode 100644 index 0f2034f..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap.common-0.2.3_dev-nspkg.pth +++ /dev/null @@ -1 +0,0 @@ -import sys,types,os; p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('leap',)); ie = os.path.exists(os.path.join(p,'__init__.py')); m = not ie and sys.modules.setdefault('leap',types.ModuleType('leap')); mp = (m or []) and m.__dict__.setdefault('__path__',[]); (p not in mp) and mp.append(p) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/__init__.py b/debian/python-leap.common/usr/share/pyshared/leap/common/__init__.py deleted file mode 100644 index 5bcbb38..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -import logging - -from leap.common import certs -from leap.common import check -from leap.common import files -from leap.common import events - -logger = logging.getLogger(__name__) - -try: -    import pygeoip -    HAS_GEOIP = True -except ImportError: -    #logger.debug('PyGeoIP not found. Disabled Geo support.') -    HAS_GEOIP = False - -__all__ = ["certs", "check", "files", "events"] - -__version__ = "0.2.3-dev" diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/certs.py b/debian/python-leap.common/usr/share/pyshared/leap/common/certs.py deleted file mode 100644 index 4cb70dd..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/certs.py +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding: utf-8 -*- -# certs.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. - -""" -Implements cert checks and helpers -""" - -import os -import time -import logging - -from OpenSSL import crypto -from dateutil.parser import parse as dateparse - -from leap.common.check import leap_assert - -logger = logging.getLogger(__name__) - - -def get_cert_from_string(string): -    """ -    Returns the x509 from the contents of this string - -    @param string: certificate contents as downloaded -    @type string: str - -    @return: x509 or None -    """ -    leap_assert(string, "We need something to load") - -    x509 = None -    try: -        x509 = crypto.load_certificate(crypto.FILETYPE_PEM, string) -    except Exception as e: -        logger.error("Something went wrong while loading the certificate: %r" -                     % (e,)) -    return x509 - - -def get_privatekey_from_string(string): -    """ -    Returns the private key from the contents of this string - -    @param string: private key contents as downloaded -    @type string: str - -    @return: private key or None -    """ -    leap_assert(string, "We need something to load") - -    pkey = None -    try: -        pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, string) -    except Exception as e: -        logger.error("Something went wrong while loading the certificate: %r" -                     % (e,)) -    return pkey - - -def get_digest(cert_data, method): -    """ -    Returns the digest for the cert_data using the method specified - -    @param cert_data: certificate data in string form -    @type cert_data: str -    @param method: method to be used for digest -    @type method: str - -    @rtype: str -    """ -    x509 = get_cert_from_string(cert_data) -    digest = x509.digest(method).replace(":", "").lower() - -    return digest - - -def can_load_cert_and_pkey(string): -    """ -    Loads certificate and private key from a buffer, returns True if -    everything went well, False otherwise - -    @param string: buffer containing the cert and private key -    @type string: str or any kind of buffer - -    @rtype: bool -    """ -    can_load = True - -    try: -        cert = get_cert_from_string(string) -        key = get_privatekey_from_string(string) - -        leap_assert(cert, 'The certificate could not be loaded') -        leap_assert(key, 'The private key could not be loaded') -    except Exception as e: -        can_load = False -        logger.error("Something went wrong while trying to load " -                     "the certificate: %r" % (e,)) - -    return can_load - - -def is_valid_pemfile(cert): -    """ -    Checks that the passed string is a valid pem certificate - -    @param cert: String containing pem content -    @type cert: str - -    @rtype: bool -    """ -    leap_assert(cert, "We need a cert to load") - -    return can_load_cert_and_pkey(cert) - - -def get_cert_time_boundaries(certfile): -    """ -    Returns the time boundaries for the certificate saved in certfile - -    @param certfile: path to certificate -    @type certfile: str - -    @rtype: tuple (from, to) -    """ -    cert = get_cert_from_string(certfile) -    leap_assert(cert, 'There was a problem loading the certificate') - -    fromts, tots = (cert.get_notBefore(), cert.get_notAfter()) -    from_, to_ = map( -        lambda ts: time.gmtime(time.mktime(dateparse(ts).timetuple())), -        (fromts, tots)) -    return from_, to_ - - -def should_redownload(certfile, now=time.gmtime): -    """ -    Returns True if any of the checks don't pass, False otherwise - -    @param certfile: path to certificate -    @type certfile: str -    @param now: current date function, ONLY USED FOR TESTING - -    @rtype: bool -    """ -    exists = os.path.isfile(certfile) - -    if not exists: -        return True - -    certdata = None -    try: -        with open(certfile, "r") as f: -            certdata = f.read() -            if not is_valid_pemfile(certdata): -                return True -    except: -        return True - -    valid_from, valid_to = get_cert_time_boundaries(certdata) - -    if not (valid_from < now() < valid_to): -        return True - -    return False diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/check.py b/debian/python-leap.common/usr/share/pyshared/leap/common/check.py deleted file mode 100644 index 359673b..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/check.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# check.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. -""" -Set of functions to help checking situations -""" - -import inspect -import logging -import traceback - - -logger = logging.getLogger(__name__) - - -def leap_assert(condition, message=""): -    """ -    Asserts the condition and displays the message if that's not -    met. It also logs the error and its backtrace. - -    @param condition: condition to check -    @type condition: bool -    @param message: message to display if the condition isn't met -    @type message: str -    """ -    if not condition: -        logger.error("Bug: %s" % (message,)) -        try: -            frame = inspect.currentframe() -            stack_trace = traceback.format_stack(frame) -            logger.error(''.join(stack_trace)) -        except Exception as e: -            logger.error("Bug in leap_assert: %r" % (e,)) -    assert condition, message - - -def leap_assert_type(var, expectedType): -    """ -    Helper assert check for a variable's expected type - -    @param var: variable to check -    @type var: any -    @param expectedType: type to check agains -    @type expectedType: type -    """ -    leap_assert(isinstance(var, expectedType), -                "Expected type %r instead of %r" % -                (expectedType, type(var))) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/config/__init__.py b/debian/python-leap.common/usr/share/pyshared/leap/common/config/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/config/__init__.py +++ /dev/null diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/config/baseconfig.py b/debian/python-leap.common/usr/share/pyshared/leap/common/config/baseconfig.py deleted file mode 100644 index 146f1e4..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/config/baseconfig.py +++ /dev/null @@ -1,185 +0,0 @@ -# -*- coding: utf-8 -*- -# baseconfig.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. - -""" -Implements the abstract base class for configuration -""" - -import copy -import logging -import functools -import os - -from abc import ABCMeta, abstractmethod - -from leap.common.check import leap_assert -from leap.common.files import mkdir_p -from leap.common.config.pluggableconfig import PluggableConfig -from leap.common.config.prefixers import get_platform_prefixer - -logger = logging.getLogger(__name__) - - -class BaseConfig: -    """ -    Abstract base class for any JSON based configuration -    """ - -    __metaclass__ = ABCMeta - -    """ -    Standalone is a class wide parameter - -    @param standalone: if True it will return the prefix for a -    standalone application. Otherwise, it will return the system -    default for configuration storage. -    @type standalone: bool -    """ -    standalone = False - -    def __init__(self): -        self._data = {} -        self._config_checker = None - -    @abstractmethod -    def _get_spec(self): -        """ -        Returns the spec object for the specific configuration -        """ -        return None - -    def _safe_get_value(self, key): -        """ -        Tries to return a value only if the config has already been loaded - -        @rtype: depends on the config structure, dict, str, array, int -        @return: returns the value for the specified key in the config -        """ -        leap_assert(self._config_checker, "Load the config first") -        return self._config_checker.config.get(key, None) - -    def get_path_prefix(self): -        """ -        Returns the platform dependant path prefixer -        """ -        return get_platform_prefixer().get_path_prefix( -            standalone=self.standalone) - -    def loaded(self): -        """ -        Returns True if the configuration has been already -        loaded. False otherwise -        """ -        return self._config_checker is not None - -    def save(self, path_list): -        """ -        Saves the current configuration to disk - -        @param path_list: list of components that form the relative -        path to configuration. The absolute path will be calculated -        depending on the platform. -        @type path_list: list - -        @return: True if saved to disk correctly, False otherwise -        """ -        config_path = os.path.join(self.get_path_prefix(), *(path_list[:-1])) -        mkdir_p(config_path) - -        try: -            self._config_checker.serialize(os.path.join(config_path, -                                                        path_list[-1])) -        except Exception as e: -            logger.warning("%s" % (e,)) -            raise -        return True - -    def load(self, path="", data=None, mtime=None): -        """ -        Loads the configuration from disk - -        @type path: str -        @param path: relative path to configuration. The absolute path -        will be calculated depending on the platform - -        @return: True if loaded from disk correctly, False otherwise -        """ - -        config_path = os.path.join(self.get_path_prefix(), -                                   path) - -        self._config_checker = PluggableConfig(format="json") -        self._config_checker.options = copy.deepcopy(self._get_spec()) - -        try: -            if data is None: -                self._config_checker.load(fromfile=config_path, mtime=mtime) -            else: -                self._config_checker.load(data, mtime=mtime) -        except Exception as e: -            logger.warning("Something went wrong while loading " + -                           "the config from %s\n%s" % (config_path, e)) -            self._config_checker = None -            return False -        return True - - -class LocalizedKey(object): -    """ -    Decorator used for keys that are localized in a configuration -    """ - -    def __init__(self, func, **kwargs): -        self._func = func - -    def __call__(self, instance, lang="en"): -        """ -        Tries to return the string for the specified language, otherwise -        informs the problem and returns an empty string - -        @param lang: language code -        @type lang: str - -        @return: localized value from the possible values returned by -        self._func -        """ -        descriptions = self._func(instance) -        description_lang = "" -        config_lang = "en" -        for key in descriptions.keys(): -            if lang.startswith(key): -                config_lang = key -                break - -        description_lang = descriptions[config_lang] -        return description_lang - -    def __get__(self, instance, instancetype): -        """ -        Implement the descriptor protocol to make decorating instance -        method possible. -        """ -        # Return a partial function with the first argument is the instance -        # of the class decorated. -        return functools.partial(self.__call__, instance) - -if __name__ == "__main__": -    try: -        config = BaseConfig()  # should throw TypeError for _get_spec -    except Exception as e: -        assert isinstance(e, TypeError), "Something went wrong" -        print "Abstract BaseConfig class is working as expected" diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/config/pluggableconfig.py b/debian/python-leap.common/usr/share/pyshared/leap/common/config/pluggableconfig.py deleted file mode 100644 index 8535fa6..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/config/pluggableconfig.py +++ /dev/null @@ -1,475 +0,0 @@ -# -*- coding: utf-8 -*- -# pluggableconfig.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. - -""" -generic configuration handlers -""" -import copy -import json -import logging -import os -import time -import urlparse - -import jsonschema - -#from leap.base.util.translations import LEAPTranslatable -from leap.common.check import leap_assert - - -logger = logging.getLogger(__name__) - - -__all__ = ['PluggableConfig', -           'adaptors', -           'types', -           'UnknownOptionException', -           'MissingValueException', -           'ConfigurationProviderException', -           'TypeCastException'] - -# exceptions - - -class UnknownOptionException(Exception): -    """exception raised when a non-configuration -    value is present in the configuration""" - - -class MissingValueException(Exception): -    """exception raised when a required value is missing""" - - -class ConfigurationProviderException(Exception): -    """exception raised when a configuration provider is missing, etc""" - - -class TypeCastException(Exception): -    """exception raised when a -    configuration item cannot be coerced to a type""" - - -class ConfigAdaptor(object): -    """ -    abstract base class for config adaotors for -    serialization/deserialization and custom validation -    and type casting. -    """ -    def read(self, filename): -        raise NotImplementedError("abstract base class") - -    def write(self, config, filename): -        with open(filename, 'w') as f: -            self._write(f, config) - -    def _write(self, fp, config): -        raise NotImplementedError("abstract base class") - -    def validate(self, config, schema): -        raise NotImplementedError("abstract base class") - - -adaptors = {} - - -class JSONSchemaEncoder(json.JSONEncoder): -    """ -    custom default encoder that -    casts python objects to json objects for -    the schema validation -    """ -    def default(self, obj): -        if obj is str: -            return 'string' -        if obj is unicode: -            return 'string' -        if obj is int: -            return 'integer' -        if obj is list: -            return 'array' -        if obj is dict: -            return 'object' -        if obj is bool: -            return 'boolean' - - -class JSONAdaptor(ConfigAdaptor): -    indent = 2 -    extensions = ['json'] - -    def read(self, _from): -        if isinstance(_from, file): -            _from_string = _from.read() -        if isinstance(_from, str): -            _from_string = _from -        return json.loads(_from_string) - -    def _write(self, fp, config): -        fp.write(json.dumps(config, -                 indent=self.indent, -                 sort_keys=True)) - -    def validate(self, config, schema_obj): -        schema_json = JSONSchemaEncoder().encode(schema_obj) -        schema = json.loads(schema_json) -        jsonschema.validate(config, schema) - - -adaptors['json'] = JSONAdaptor() - -# -# Adaptors -# -# Allow to apply a predefined set of types to the -# specs, so it checks the validity of formats and cast it -# to proper python types. - -# TODO: -# - HTTPS uri - - -class DateType(object): -    fmt = '%Y-%m-%d' - -    def to_python(self, data): -        return time.strptime(data, self.fmt) - -    def get_prep_value(self, data): -        return time.strftime(self.fmt, data) - - -class TranslatableType(object): -    """ -    a type that casts to LEAPTranslatable objects. -    Used for labels we get from providers and stuff. -    """ - -    def to_python(self, data): -        # TODO: add translatable -        return data  # LEAPTranslatable(data) - -    # needed? we already have an extended dict... -    #def get_prep_value(self, data): -        #return dict(data) - - -class URIType(object): - -    def to_python(self, data): -        parsed = urlparse.urlparse(data) -        if not parsed.scheme: -            raise TypeCastException("uri %s has no schema" % data) -        return parsed.geturl() - -    def get_prep_value(self, data): -        return data - - -class HTTPSURIType(object): - -    def to_python(self, data): -        parsed = urlparse.urlparse(data) -        if not parsed.scheme: -            raise TypeCastException("uri %s has no schema" % data) -        if parsed.scheme != "https": -            raise TypeCastException( -                "uri %s does not has " -                "https schema" % data) -        return parsed.geturl() - -    def get_prep_value(self, data): -        return data - - -types = { -    'date': DateType(), -    'uri': URIType(), -    'https-uri': HTTPSURIType(), -    'translatable': TranslatableType(), -} - - -class PluggableConfig(object): - -    options = {} - -    def __init__(self, -                 adaptors=adaptors, -                 types=types, -                 format=None): - -        self.config = {} -        self.adaptors = adaptors -        self.types = types -        self._format = format -        self.mtime = None -        self.dirty = False - -    @property -    def option_dict(self): -        if hasattr(self, 'options') and isinstance(self.options, dict): -            return self.options.get('properties', None) - -    def items(self): -        """ -        act like an iterator -        """ -        if isinstance(self.option_dict, dict): -            return self.option_dict.items() -        return self.options - -    def validate(self, config, format=None): -        """ -        validate config -        """ -        schema = self.options -        if format is None: -            format = self._format - -        if format: -            adaptor = self.get_adaptor(self._format) -            adaptor.validate(config, schema) -        else: -            # we really should make format mandatory... -            logger.error('no format passed to validate') - -        # first round of validation is ok. -        # now we proceed to cast types if any specified. -        self.to_python(config) - -    def to_python(self, config): -        """ -        cast types following first type and then format indications. -        """ -        unseen_options = [i for i in config if i not in self.option_dict] -        if unseen_options: -            raise UnknownOptionException( -                "Unknown options: %s" % ', '.join(unseen_options)) - -        for key, value in config.items(): -            _type = self.option_dict[key].get('type') -            if _type is None and 'default' in self.option_dict[key]: -                _type = type(self.option_dict[key]['default']) -            if _type is not None: -                tocast = True -                if not callable(_type) and isinstance(value, _type): -                    tocast = False -                if tocast: -                    try: -                        config[key] = _type(value) -                    except BaseException, e: -                        raise TypeCastException( -                            "Could not coerce %s, %s, " -                            "to type %s: %s" % (key, value, _type.__name__, e)) -            _format = self.option_dict[key].get('format', None) -            _ftype = self.types.get(_format, None) -            if _ftype: -                try: -                    config[key] = _ftype.to_python(value) -                except BaseException, e: -                    raise TypeCastException( -                        "Could not coerce %s, %s, " -                        "to format %s: %s" % (key, value, -                        _ftype.__class__.__name__, -                        e)) - -        return config - -    def prep_value(self, config): -        """ -        the inverse of to_python method, -        called just before serialization -        """ -        for key, value in config.items(): -            _format = self.option_dict[key].get('format', None) -            _ftype = self.types.get(_format, None) -            if _ftype and hasattr(_ftype, 'get_prep_value'): -                try: -                    config[key] = _ftype.get_prep_value(value) -                except BaseException, e: -                    raise TypeCastException( -                        "Could not serialize %s, %s, " -                        "by format %s: %s" % (key, value, -                        _ftype.__class__.__name__, -                        e)) -            else: -                config[key] = value -        return config - -    # methods for adding configuration - -    def get_default_values(self): -        """ -        return a config options from configuration defaults -        """ -        defaults = {} -        for key, value in self.items(): -            if 'default' in value: -                defaults[key] = value['default'] -        return copy.deepcopy(defaults) - -    def get_adaptor(self, format): -        """ -        get specified format adaptor or -        guess for a given filename -        """ -        adaptor = self.adaptors.get(format, None) -        if adaptor: -            return adaptor - -        # not registered in adaptors dict, let's try all -        for adaptor in self.adaptors.values(): -            if format in adaptor.extensions: -                return adaptor - -    def filename2format(self, filename): -        extension = os.path.splitext(filename)[-1] -        return extension.lstrip('.') or None - -    def serialize(self, filename, format=None, full=False): -        if not format: -            format = self._format -        if not format: -            format = self.filename2format(filename) -        if not format: -            raise Exception('Please specify a format') -            # TODO: more specific exception type - -        adaptor = self.get_adaptor(format) -        if not adaptor: -            raise Exception("Adaptor not found for format: %s" % format) - -        config = copy.deepcopy(self.config) -        serializable = self.prep_value(config) -        adaptor.write(serializable, filename) - -        if self.mtime: -            self.touch_mtime(filename) - -    def touch_mtime(self, filename): -        mtime = self.mtime -        os.utime(filename, (mtime, mtime)) - -    def deserialize(self, string=None, fromfile=None, format=None): -        """ -        load configuration from a file or string -        """ - -        def _try_deserialize(): -            if fromfile: -                with open(fromfile, 'r') as f: -                    content = adaptor.read(f) -            elif string: -                content = adaptor.read(string) -            return content - -        # XXX cleanup this! - -        if fromfile: -            leap_assert(os.path.exists(fromfile)) -            if not format: -                format = self.filename2format(fromfile) - -        if not format: -            format = self._format -        if format: -            adaptor = self.get_adaptor(format) -        else: -            adaptor = None - -        if adaptor: -            content = _try_deserialize() -            return content - -        # no adaptor, let's try rest of adaptors - -        adaptors = self.adaptors[:] - -        if format: -            adaptors.sort( -                key=lambda x: int( -                    format in x.extensions), -                reverse=True) - -        for adaptor in adaptors: -            content = _try_deserialize() -        return content - -    def set_dirty(self): -        self.dirty = True - -    def is_dirty(self): -        return self.dirty - -    def load(self, *args, **kwargs): -        """ -        load from string or file -        if no string of fromfile option is given, -        it will attempt to load from defaults -        defined in the schema. -        """ -        string = args[0] if args else None -        fromfile = kwargs.get("fromfile", None) -        mtime = kwargs.pop("mtime", None) -        self.mtime = mtime -        content = None - -        # start with defaults, so we can -        # have partial values applied. -        content = self.get_default_values() -        if string and isinstance(string, str): -            content = self.deserialize(string) - -        if not string and fromfile is not None: -            #import ipdb;ipdb.set_trace() -            content = self.deserialize(fromfile=fromfile) - -        if not content: -            logger.error('no content could be loaded') -            # XXX raise! -            return - -        # lazy evaluation until first level of nesting -        # to allow lambdas with context-dependant info -        # like os.path.expanduser -        for k, v in content.iteritems(): -            if callable(v): -                content[k] = v() - -        self.validate(content) -        self.config = content -        return True - - -def testmain():  # pragma: no cover - -    from tests import test_validation as t -    import pprint - -    config = PluggableConfig(_format="json") -    properties = copy.deepcopy(t.sample_spec) - -    config.options = properties -    config.load(fromfile='data.json') - -    print 'config' -    pprint.pprint(config.config) - -    config.serialize('/tmp/testserial.json') - -if __name__ == "__main__": -    testmain() diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/config/prefixers.py b/debian/python-leap.common/usr/share/pyshared/leap/common/config/prefixers.py deleted file mode 100644 index 27274bd..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/config/prefixers.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- -# prefixers.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. - -""" -Platform dependant configuration path prefixers -""" -import os -import platform - -from abc import ABCMeta, abstractmethod -from xdg import BaseDirectory - -from leap.common.check import leap_assert - - -class Prefixer: -    """ -    Abstract prefixer class -    """ - -    __metaclass__ = ABCMeta - -    @abstractmethod -    def get_path_prefix(self, standalone=False): -        """ -        Returns the platform dependant path prefixer - -        @param standalone: if True it will return the prefix for a -        standalone application. Otherwise, it will return the system -        default for configuration storage. -        @type standalone: bool -        """ -        return "" - - -def get_platform_prefixer(): -    prefixer = globals()[platform.system() + "Prefixer"] -    leap_assert(prefixer, "Unimplemented platform prefixer: %s" % -                (platform.system(),)) -    return prefixer() - - -class LinuxPrefixer(Prefixer): -    """ -    Config prefixer for the Linux platform -    """ - -    def get_path_prefix(self, standalone=False): -        """ -        Returns the platform dependant path prefixer. -        This method expects an env variable named LEAP_CLIENT_PATH if -        standalone is used. - -        @param standalone: if True it will return the prefix for a -        standalone application. Otherwise, it will return the system -        default for configuration storage. -        @type standalone: bool -        """ -        config_dir = BaseDirectory.xdg_config_home -        if not standalone: -            return config_dir -        return os.path.join(os.getcwd(), "config") - - -class DarwinPrefixer(Prefixer): -    """ -    Config prefixer for the Darwin platform -    """ - -    def get_path_prefix(self, standalone=False): -        """ -        Returns the platform dependant path prefixer. -        This method expects an env variable named LEAP_CLIENT_PATH if -        standalone is used. - -        @param standalone: if True it will return the prefix for a -        standalone application. Otherwise, it will return the system -        default for configuration storage. -        @type standalone: bool -        """ -        config_dir = BaseDirectory.xdg_config_home -        if not standalone: -            return config_dir -        return os.getenv(os.getcwd(), "config") - - -class WindowsPrefixer(Prefixer): -    """ -    Config prefixer for the Windows platform -    """ - -    def get_path_prefix(self, standalone=False): -        """ -        Returns the platform dependant path prefixer. -        This method expects an env variable named LEAP_CLIENT_PATH if -        standalone is used. - -        @param standalone: if True it will return the prefix for a -        standalone application. Otherwise, it will return the system -        default for configuration storage. -        @type standalone: bool -        """ -        config_dir = BaseDirectory.xdg_config_home - -        if not standalone: -            return config_dir -        return os.path.join(os.getcwd(), "config") - -if __name__ == "__main__": -    try: -        abs_prefixer = Prefixer() -    except Exception as e: -        assert isinstance(e, TypeError), "Something went wrong" -        print "Abstract Prefixer class is working as expected" - -    linux_prefixer = LinuxPrefixer() -    print linux_prefixer.get_path_prefix(standalone=True) -    print linux_prefixer.get_path_prefix() diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/events/__init__.py b/debian/python-leap.common/usr/share/pyshared/leap/common/events/__init__.py deleted file mode 100644 index c949080..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/events/__init__.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -# __init__.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -""" -An events mechanism that allows for signaling of events between components. -""" - -import logging -import socket - - -from leap.common.events import ( -    events_pb2, -    server, -    component, -    daemon, -) - - -logger = logging.getLogger(__name__) - - -def register(signal, callback, uid=None, replace=False, reqcbk=None, -             timeout=1000): -    """ -    Register a callback to be called when the given signal is received. - -    Will timeout after timeout ms if response has not been received. The -    timeout arg is only used for asynch requests. If a reqcbk callback has -    been supplied the timeout arg is not used. The response value will be -    returned for a synch request but nothing will be returned for an asynch -    request. - -    @param signal: the signal that causes the callback to be launched -    @type signal: int (see the `events.proto` file) -    @param callback: the callback to be called when the signal is received -    @type callback: function -    @param uid: a unique id for the callback -    @type uid: int -    @param replace: should an existent callback with same uid be replaced? -    @type replace: bool -    @param reqcbk: a callback to be called when a response from server is -        received -    @type reqcbk: function -        callback(leap.common.events.events_pb2.EventResponse) -    @param timeout: the timeout for synch calls -    @type timeout: int - -    @return: the response from server for synch calls or nothing for asynch -        calls -    @rtype: leap.common.events.events_pb2.EventsResponse or None -    """ -    return component.register(signal, callback, uid, replace, reqcbk, timeout) - - -def signal(signal, content="", mac_method="", mac="", reqcbk=None, -           timeout=1000): -    """ -    Send `signal` event to events server. - -    Will timeout after timeout ms if response has not been received. The -    timeout arg is only used for asynch requests.  If a reqcbk callback has -    been supplied the timeout arg is not used. The response value will be -    returned for a synch request but nothing will be returned for an asynch -    request. - -    @param signal: the signal that causes the callback to be launched -    @type signal: int (see the `events.proto` file) -    @param content: the contents of the event signal -    @type content: str -    @param mac_method: the method used to auth mac -    @type mac_method: str -    @param mac: the content of the auth mac -    @type mac: str -    @param reqcbk: a callback to be called when a response from server is -        received -    @type reqcbk: function -        callback(leap.common.events.events_pb2.EventResponse) -    @param timeout: the timeout for synch calls -    @type timeout: int - -    @return: the response from server for synch calls or nothing for asynch -        calls -    @rtype: leap.common.events.events_pb2.EventsResponse or None -    """ -    return component.signal(signal, content, mac_method, mac, reqcbk, timeout) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/events/component.py b/debian/python-leap.common/usr/share/pyshared/leap/common/events/component.py deleted file mode 100644 index 0cf0e38..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/events/component.py +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: utf-8 -*- -# component.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -""" -The component end point of the events mechanism. - -Components are the communicating parties of the events mechanism. They -communicate by sending messages to a server, which in turn redistributes -messages to other components. - -When a component registers a callback for a given signal, it also tells the -server that it wants to be notified whenever signals of that type are sent by -some other component. -""" - - -import logging -import threading - - -from protobuf.socketrpc import RpcService -from leap.common.events import ( -    events_pb2 as proto, -    server, -    daemon, -    mac_auth, -) - - -logger = logging.getLogger(__name__) - - -# the `registered_callbacks` dictionary below should have the following -# format: -# -#     { event_signal: [ (uid, callback), ... ], ... } -# -registered_callbacks = {} - - -class CallbackAlreadyRegistered(Exception): -    """ -    Raised when trying to register an already registered callback. -    """ - - -def ensure_component_daemon(): -    """ -    Ensure the component daemon is running and listening for incoming -    messages. - -    @return: the daemon instance -    @rtype: EventsComponentDaemon -    """ -    import time -    daemon = EventsComponentDaemon.ensure(0) -    logger.debug('ensure component daemon') - -    # Because we use a random port we want to wait until a port is assigned to -    # local component daemon. - -    while not (EventsComponentDaemon.get_instance() and -               EventsComponentDaemon.get_instance().get_port()): -        time.sleep(0.1) -    return daemon - - -def register(signal, callback, uid=None, replace=False, reqcbk=None, -             timeout=1000): -    """ -    Registers a callback to be called when a specific signal event is -    received. - -    Will timeout after timeout ms if response has not been received. The -    timeout arg is only used for asynch requests. If a reqcbk callback has -    been supplied the timeout arg is not used. The response value will be -    returned for a synch request but nothing will be returned for an asynch -    request. - -    @param signal: the signal that causes the callback to be launched -    @type signal: int (see the `events.proto` file) -    @param callback: the callback to be called when the signal is received -    @type callback: function -        callback(leap.common.events.events_pb2.SignalRequest) -    @param uid: a unique id for the callback -    @type uid: int -    @param replace: should an existent callback with same uid be replaced? -    @type replace: bool -    @param reqcbk: a callback to be called when a response from server is -        received -    @type reqcbk: function -        callback(leap.common.events.events_pb2.EventResponse) -    @param timeout: the timeout for synch calls -    @type timeout: int - -    Might raise a CallbackAlreadyRegistered exception if there's already a -    callback identified by the given uid and replace is False. - -    @return: the response from server for synch calls or nothing for asynch -        calls -    @rtype: leap.common.events.events_pb2.EventsResponse or None -    """ -    ensure_component_daemon()  # so we can receive registered signals -    # register callback locally -    if signal not in registered_callbacks: -        registered_callbacks[signal] = [] -    cbklist = registered_callbacks[signal] -    if uid and filter(lambda (x, y): x == uid, cbklist): -        if not replace: -            raise CallbackAlreadyRegisteredException() -        else: -            registered_callbacks[signal] = filter(lambda(x, y): x != uid, -                                                  cbklist) -    registered_callbacks[signal].append((uid, callback)) -    # register callback on server -    request = proto.RegisterRequest() -    request.event = signal -    request.port = EventsComponentDaemon.get_instance().get_port() -    request.mac_method = mac_auth.MacMethod.MAC_NONE -    request.mac = "" -    service = RpcService(proto.EventsServerService_Stub, -                         server.SERVER_PORT, 'localhost') -    logger.info("Sending registration request to server on port %s: %s", -            server.SERVER_PORT, -            str(request)) -    return service.register(request, callback=reqcbk, timeout=timeout) - - -def signal(signal, content="", mac_method="", mac="", reqcbk=None, -           timeout=1000): -    """ -    Send `signal` event to events server. - -    Will timeout after timeout ms if response has not been received. The -    timeout arg is only used for asynch requests.  If a reqcbk callback has -    been supplied the timeout arg is not used. The response value will be -    returned for a synch request but nothing will be returned for an asynch -    request. - -    @param signal: the signal that causes the callback to be launched -    @type signal: int (see the `events.proto` file) -    @param content: the contents of the event signal -    @type content: str -    @param mac_method: the method used for auth mac -    @type mac_method: str -    @param mac: the content of the auth mac -    @type mac: str -    @param reqcbk: a callback to be called when a response from server is -        received -    @type reqcbk: function -        callback(leap.common.events.events_pb2.EventResponse) -    @param timeout: the timeout for synch calls -    @type timeout: int - -    @return: the response from server for synch calls or nothing for asynch -        calls -    @rtype: leap.common.events.events_pb2.EventsResponse or None -    """ -    request = proto.SignalRequest() -    request.event = signal -    request.content = content -    request.mac_method = mac_method -    request.mac = mac -    service = RpcService(proto.EventsServerService_Stub, server.SERVER_PORT, -                         'localhost') -    logger.info("Sending signal to server: %s", str(request)) -    return service.signal(request, callback=reqcbk, timeout=timeout) - - -class EventsComponentService(proto.EventsComponentService): -    """ -    Service for receiving signal events in components. -    """ - -    def __init__(self): -        proto.EventsComponentService.__init__(self) - -    def signal(self, controller, request, done): -        """ -        Receive a signal and run callbacks registered for that signal. - -        This method is called whenever a signal request is received from -        server. - -        @param controller: used to mediate a single method call -        @type controller: protobuf.socketrpc.controller.SocketRpcController -        @param request: the request received from the component -        @type request: leap.common.events.events_pb2.SignalRequest -        @param done: callback to be called when done -        @type done: protobuf.socketrpc.server.Callback -        """ -        logger.info('Received signal from server: %s' % str(request)) - -        # run registered callbacks -        # TODO: verify authentication using mac in incoming message -        if request.event in registered_callbacks: -            for (_, cbk) in registered_callbacks[request.event]: -                # callbacks should be prepared to receive a -                # events_pb2.SignalRequest. -                cbk(request) - -        # send response back to server -        response = proto.EventResponse() -        response.status = proto.EventResponse.OK -        done.run(response) - - -class EventsComponentDaemon(daemon.EventsSingletonDaemon): -    """ -    A daemon that listens for incoming events from server. -    """ - -    @classmethod -    def ensure(cls, port): -        """ -        Make sure the daemon is running on the given port. - -        @param port: the port in which the daemon should listen -        @type port: int - -        @return: a daemon instance -        @rtype: EventsComponentDaemon -        """ -        return cls.ensure_service(port, EventsComponentService()) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/events/daemon.py b/debian/python-leap.common/usr/share/pyshared/leap/common/events/daemon.py deleted file mode 100644 index d2c7b9b..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/events/daemon.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- coding: utf-8 -*- -# daemon.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -""" -A singleton daemon for running RPC services using protobuf.socketrpc. -""" - - -import logging -import threading - - -from protobuf.socketrpc.server import ( -    SocketRpcServer, -    ThreadedTCPServer, -    SocketHandler, -) - - -logger = logging.getLogger(__name__) - - -class ServiceAlreadyRunningException(Exception): -    """ -    Raised whenever a service is already running in this process but someone -    attemped to start it in a different port. -    """ - - -class EventsRpcServer(SocketRpcServer): -    """ -    RPC server used in server and component interfaces to receive messages. -    """ - -    def __init__(self, port, host='localhost'): -        """ -        Initialize a RPC server. - -        @param port: the port in which to listen for incoming messages -        @type port: int -        @param host: the address to bind to -        @type host: str -        """ -        SocketRpcServer.__init__(self, port, host) -        self._server = None - -    def run(self): -        """ -        Run the server. -        """ -        logger.info('Running server on port %d.' % self.port) -        # parent implementation does not hold the server instance, so we do it -        # here. -        self._server = ThreadedTCPServer((self.host, self.port), -                                         SocketHandler, self) -        # if we chose to use a random port, fetch the port number info. -        if self.port is 0: -            self.port = self._server.socket.getsockname()[1] -        self._server.serve_forever() - -    def stop(self): -        """ -        Stop the server. -        """ -        self._server.shutdown() - - -class EventsSingletonDaemon(threading.Thread): -    """ -    Singleton class for for launching and terminating a daemon. - -    This class is used so every part of the mechanism that needs to listen for -    messages can launch its own daemon (thread) to do the job. -    """ - -    # Singleton instance -    __instance = None - -    def __new__(cls, *args, **kwargs): -        """ -        Return a singleton instance if it exists or create and initialize one. -        """ -        if len(args) is not 2: -            raise TypeError("__init__() takes exactly 2 arguments (%d given)" -                            % len(args)) -        if cls.__instance is None: -            cls.__instance = object.__new__( -                EventsSingletonDaemon) -            cls.__initialize(cls.__instance, args[0], args[1]) -        return cls.__instance - -    @staticmethod -    def __initialize(self, port, service): -        """ -        Initialize a singleton daemon. - -        This is a static method disguised as instance method that actually -        does the initialization of the daemon instance. - -        @param port: the port in which to listen for incoming messages -        @type port: int -        @param service: the service to provide in this daemon -        @type service: google.protobuf.service.Service -        """ -        threading.Thread.__init__(self) -        self._port = port -        self._service = service -        self._server = EventsRpcServer(self._port) -        self._server.registerService(self._service) -        self.daemon = True - -    def __init__(self): -        """ -        Singleton placeholder initialization method. - -        Initialization is made in __new__ so we can always return the same -        instance upon object creation. -        """ -        pass - -    @classmethod -    def ensure(cls, port): -        """ -        Make sure the daemon instance is running. - -        Each implementation of this method should call `self.ensure_service` -        with the appropriate service from the `events.proto` definitions, and -        return the daemon instance. - -        @param port: the port in which the daemon should be listening -        @type port: int - -        @return: a daemon instance -        @rtype: EventsSingletonDaemon -        """ -        raise NotImplementedError(self.ensure) - -    @classmethod -    def ensure_service(cls, port, service): -        """ -        Start the singleton instance if not already running. - -        Might return ServiceAlreadyRunningException - -        @param port: the port in which the daemon should be listening -        @type port: int - -        @return: a daemon instance -        @rtype: EventsSingletonDaemon -        """ -        daemon = cls(port, service) -        if not daemon.is_alive(): -            daemon.start() -        elif port and port != cls.__instance._port: -            # service is running in this process but someone is trying to -            # start it in another port -            raise ServiceAlreadyRunningException( -                "Service is already running in this process on port %d." -                % self.__instance._port) -        return daemon - -    @classmethod -    def get_instance(cls): -        """ -        Retrieve singleton instance of this daemon. - -        @return: a daemon instance -        @rtype: EventsSingletonDaemon -        """ -        return cls.__instance - -    def run(self): -        """ -        Run the server. -        """ -        self._server.run() - -    def stop(self): -        """ -        Stop the daemon. -        """ -        self._server.stop() - -    def get_port(self): -        """ -        Retrieve the value of the port to which the service running in this -        daemon is binded to. - -        @return: the port to which the daemon is binded to -        @rtype: int -        """ -        if self._port is 0: -            self._port = self._server.port -        return self._port diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/events/events_pb2.py b/debian/python-leap.common/usr/share/pyshared/leap/common/events/events_pb2.py deleted file mode 100644 index a4f1df4..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/events/events_pb2.py +++ /dev/null @@ -1,371 +0,0 @@ -# Generated by the protocol buffer compiler.  DO NOT EDIT! - -from google.protobuf import descriptor -from google.protobuf import message -from google.protobuf import reflection -from google.protobuf import service -from google.protobuf import service_reflection -from google.protobuf import descriptor_pb2 -# @@protoc_insertion_point(imports) - - -DESCRIPTOR = descriptor.FileDescriptor( -    name='events.proto', -    package='leap.common.events', -    serialized_pb='\n\x0c\x65vents.proto\x12\x12leap.common.events\"\x97\x01\n\rSignalRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0f\n\x07\x63ontent\x18\x02 \x02(\t\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\x12\x12\n\nenc_method\x18\x05 \x01(\t\x12\x16\n\x0e\x65rror_occurred\x18\x06 \x01(\x08\"j\n\x0fRegisterRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0c\n\x04port\x18\x02 \x02(\x05\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\"\x82\x01\n\rEventResponse\x12\x38\n\x06status\x18\x01 \x02(\x0e\x32(.leap.common.events.EventResponse.Status\x12\x0e\n\x06result\x18\x02 \x01(\t\"\'\n\x06Status\x12\x06\n\x02OK\x10\x01\x12\n\n\x06UNAUTH\x10\x02\x12\t\n\x05\x45RROR\x10\x03*\xe7\x02\n\x05\x45vent\x12\x15\n\x11\x43LIENT_SESSION_ID\x10\x01\x12\x0e\n\nCLIENT_UID\x10\x02\x12\x19\n\x15SOLEDAD_CREATING_KEYS\x10\x03\x12\x1e\n\x1aSOLEDAD_DONE_CREATING_KEYS\x10\x04\x12\x1a\n\x16SOLEDAD_UPLOADING_KEYS\x10\x05\x12\x1f\n\x1bSOLEDAD_DONE_UPLOADING_KEYS\x10\x06\x12\x1c\n\x18SOLEDAD_DOWNLOADING_KEYS\x10\x07\x12!\n\x1dSOLEDAD_DONE_DOWNLOADING_KEYS\x10\x08\x12\x1c\n\x18SOLEDAD_NEW_DATA_TO_SYNC\x10\t\x12\x1a\n\x16SOLEDAD_DONE_DATA_SYNC\x10\n\x12\x17\n\x13UPDATER_NEW_UPDATES\x10\x0b\x12\x19\n\x15UPDATER_DONE_UPDATING\x10\x0c\x12\x10\n\x0cRAISE_WINDOW\x10\r2\xb9\x01\n\x13\x45ventsServerService\x12R\n\x08register\x12#.leap.common.events.RegisterRequest\x1a!.leap.common.events.EventResponse\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponse2h\n\x16\x45ventsComponentService\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponseB\x03\x90\x01\x01') - -_EVENT = descriptor.EnumDescriptor( -    name='Event', -    full_name='leap.common.events.Event', -    filename=None, -    file=DESCRIPTOR, -    values=[ -        descriptor.EnumValueDescriptor( -            name='CLIENT_SESSION_ID', index=0, number=1, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='CLIENT_UID', index=1, number=2, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_CREATING_KEYS', index=2, number=3, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_DONE_CREATING_KEYS', index=3, number=4, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_UPLOADING_KEYS', index=4, number=5, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_DONE_UPLOADING_KEYS', index=5, number=6, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_DOWNLOADING_KEYS', index=6, number=7, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_DONE_DOWNLOADING_KEYS', index=7, number=8, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_NEW_DATA_TO_SYNC', index=8, number=9, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='SOLEDAD_DONE_DATA_SYNC', index=9, number=10, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='UPDATER_NEW_UPDATES', index=10, number=11, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='UPDATER_DONE_UPDATING', index=11, number=12, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='RAISE_WINDOW', index=12, number=13, -            options=None, -            type=None), -    ], -    containing_type=None, -    options=None, -    serialized_start=432, -    serialized_end=791, -) - - -CLIENT_SESSION_ID = 1 -CLIENT_UID = 2 -SOLEDAD_CREATING_KEYS = 3 -SOLEDAD_DONE_CREATING_KEYS = 4 -SOLEDAD_UPLOADING_KEYS = 5 -SOLEDAD_DONE_UPLOADING_KEYS = 6 -SOLEDAD_DOWNLOADING_KEYS = 7 -SOLEDAD_DONE_DOWNLOADING_KEYS = 8 -SOLEDAD_NEW_DATA_TO_SYNC = 9 -SOLEDAD_DONE_DATA_SYNC = 10 -UPDATER_NEW_UPDATES = 11 -UPDATER_DONE_UPDATING = 12 -RAISE_WINDOW = 13 - - -_EVENTRESPONSE_STATUS = descriptor.EnumDescriptor( -    name='Status', -    full_name='leap.common.events.EventResponse.Status', -    filename=None, -    file=DESCRIPTOR, -    values=[ -        descriptor.EnumValueDescriptor( -            name='OK', index=0, number=1, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='UNAUTH', index=1, number=2, -            options=None, -            type=None), -        descriptor.EnumValueDescriptor( -            name='ERROR', index=2, number=3, -            options=None, -            type=None), -    ], -    containing_type=None, -    options=None, -    serialized_start=390, -    serialized_end=429, -) - - -_SIGNALREQUEST = descriptor.Descriptor( -    name='SignalRequest', -    full_name='leap.common.events.SignalRequest', -    filename=None, -    file=DESCRIPTOR, -    containing_type=None, -    fields=[ -        descriptor.FieldDescriptor( -            name='event', full_name='leap.common.events.SignalRequest.event', index=0, -            number=1, type=14, cpp_type=8, label=2, -            has_default_value=False, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='content', full_name='leap.common.events.SignalRequest.content', index=1, -      number=2, type=9, cpp_type=9, label=2, -      has_default_value=False, default_value=unicode("", "utf-8"), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='mac_method', full_name='leap.common.events.SignalRequest.mac_method', index=2, -      number=3, type=9, cpp_type=9, label=2, -      has_default_value=False, default_value=unicode("", "utf-8"), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='mac', full_name='leap.common.events.SignalRequest.mac', index=3, -      number=4, type=12, cpp_type=9, label=2, -      has_default_value=False, default_value="", -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='enc_method', full_name='leap.common.events.SignalRequest.enc_method', index=4, -      number=5, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=unicode("", "utf-8"), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='error_occurred', full_name='leap.common.events.SignalRequest.error_occurred', index=5, -      number=6, type=8, cpp_type=7, label=1, -      has_default_value=False, default_value=False, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  serialized_start=37, -  serialized_end=188, -) - - -_REGISTERREQUEST = descriptor.Descriptor( -  name='RegisterRequest', -  full_name='leap.common.events.RegisterRequest', -  filename=None, -  file=DESCRIPTOR, -  containing_type=None, -  fields=[ -    descriptor.FieldDescriptor( -      name='event', full_name='leap.common.events.RegisterRequest.event', index=0, -      number=1, type=14, cpp_type=8, label=2, -      has_default_value=False, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='port', full_name='leap.common.events.RegisterRequest.port', index=1, -      number=2, type=5, cpp_type=1, label=2, -      has_default_value=False, default_value=0, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='mac_method', full_name='leap.common.events.RegisterRequest.mac_method', index=2, -      number=3, type=9, cpp_type=9, label=2, -      has_default_value=False, default_value=unicode("", "utf-8"), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='mac', full_name='leap.common.events.RegisterRequest.mac', index=3, -      number=4, type=12, cpp_type=9, label=2, -      has_default_value=False, default_value="", -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  serialized_start=190, -  serialized_end=296, -) - - -_EVENTRESPONSE = descriptor.Descriptor( -  name='EventResponse', -  full_name='leap.common.events.EventResponse', -  filename=None, -  file=DESCRIPTOR, -  containing_type=None, -  fields=[ -    descriptor.FieldDescriptor( -      name='status', full_name='leap.common.events.EventResponse.status', index=0, -      number=1, type=14, cpp_type=8, label=2, -      has_default_value=False, default_value=1, -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -    descriptor.FieldDescriptor( -      name='result', full_name='leap.common.events.EventResponse.result', index=1, -      number=2, type=9, cpp_type=9, label=1, -      has_default_value=False, default_value=unicode("", "utf-8"), -      message_type=None, enum_type=None, containing_type=None, -      is_extension=False, extension_scope=None, -      options=None), -  ], -  extensions=[ -  ], -  nested_types=[], -  enum_types=[ -    _EVENTRESPONSE_STATUS, -  ], -  options=None, -  is_extendable=False, -  extension_ranges=[], -  serialized_start=299, -  serialized_end=429, -) - -_SIGNALREQUEST.fields_by_name['event'].enum_type = _EVENT -_REGISTERREQUEST.fields_by_name['event'].enum_type = _EVENT -_EVENTRESPONSE.fields_by_name['status'].enum_type = _EVENTRESPONSE_STATUS -_EVENTRESPONSE_STATUS.containing_type = _EVENTRESPONSE; -DESCRIPTOR.message_types_by_name['SignalRequest'] = _SIGNALREQUEST -DESCRIPTOR.message_types_by_name['RegisterRequest'] = _REGISTERREQUEST -DESCRIPTOR.message_types_by_name['EventResponse'] = _EVENTRESPONSE - - -class SignalRequest(message.Message): -    __metaclass__ = reflection.GeneratedProtocolMessageType -    DESCRIPTOR = _SIGNALREQUEST - -    # @@protoc_insertion_point(class_scope:leap.common.events.SignalRequest) - - -class RegisterRequest(message.Message): -    __metaclass__ = reflection.GeneratedProtocolMessageType -    DESCRIPTOR = _REGISTERREQUEST - -    # @@protoc_insertion_point(class_scope:leap.common.events.RegisterRequest) - - -class EventResponse(message.Message): -    __metaclass__ = reflection.GeneratedProtocolMessageType -    DESCRIPTOR = _EVENTRESPONSE - -    # @@protoc_insertion_point(class_scope:leap.common.events.EventResponse) - - -_EVENTSSERVERSERVICE = descriptor.ServiceDescriptor( -  name='EventsServerService', -  full_name='leap.common.events.EventsServerService', -  file=DESCRIPTOR, -  index=0, -  options=None, -  serialized_start=794, -  serialized_end=979, -  methods=[ -  descriptor.MethodDescriptor( -    name='register', -    full_name='leap.common.events.EventsServerService.register', -    index=0, -    containing_service=None, -    input_type=_REGISTERREQUEST, -    output_type=_EVENTRESPONSE, -    options=None, -  ), -  descriptor.MethodDescriptor( -    name='signal', -    full_name='leap.common.events.EventsServerService.signal', -    index=1, -    containing_service=None, -    input_type=_SIGNALREQUEST, -    output_type=_EVENTRESPONSE, -    options=None, -  ), -]) - - -class EventsServerService(service.Service): -    __metaclass__ = service_reflection.GeneratedServiceType -    DESCRIPTOR = _EVENTSSERVERSERVICE - - -class EventsServerService_Stub(EventsServerService): -    __metaclass__ = service_reflection.GeneratedServiceStubType -    DESCRIPTOR = _EVENTSSERVERSERVICE - - -_EVENTSCOMPONENTSERVICE = descriptor.ServiceDescriptor( -  name='EventsComponentService', -  full_name='leap.common.events.EventsComponentService', -  file=DESCRIPTOR, -  index=1, -  options=None, -  serialized_start=981, -  serialized_end=1085, -  methods=[ -  descriptor.MethodDescriptor( -    name='signal', -    full_name='leap.common.events.EventsComponentService.signal', -    index=0, -    containing_service=None, -    input_type=_SIGNALREQUEST, -    output_type=_EVENTRESPONSE, -    options=None, -  ), -]) - - -class EventsComponentService(service.Service): -    __metaclass__ = service_reflection.GeneratedServiceType -    DESCRIPTOR = _EVENTSCOMPONENTSERVICE - - -class EventsComponentService_Stub(EventsComponentService): -    __metaclass__ = service_reflection.GeneratedServiceStubType -    DESCRIPTOR = _EVENTSCOMPONENTSERVICE - -# @@protoc_insertion_point(module_scope) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/events/mac_auth.py b/debian/python-leap.common/usr/share/pyshared/leap/common/events/mac_auth.py deleted file mode 100644 index 49d48f7..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/events/mac_auth.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# mac_auth.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -""" -Authentication system for events. - -This is not implemented yet. -""" - - -class MacMethod(object): -    """ -    Representation of possible MAC authentication methods. -    """ - -    MAC_NONE = 'none' -    MAC_HMAC = 'hmac' diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/events/server.py b/debian/python-leap.common/usr/share/pyshared/leap/common/events/server.py deleted file mode 100644 index 16c6513..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/events/server.py +++ /dev/null @@ -1,149 +0,0 @@ -# -*- coding: utf-8 -*- -# server.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -""" -A server for the events mechanism. - -A server can receive different kinds of requests from components: - -  1. Registration request: store component port number to be notified when -     a specific signal arrives. - -  2. Signal request: redistribute the signal to registered components. -""" -import logging -import socket - - -from protobuf.socketrpc import RpcService -from leap.common.events import ( -    events_pb2 as proto, -    daemon, -) - - -logger = logging.getLogger(__name__) - - -SERVER_PORT = 8090 - -# the `registered_components` dictionary below should have the following -# format: -# -#     { event_signal: [ port, ... ], ... } -# -registered_components = {} - - -def ensure_server(port=SERVER_PORT): -    """ -    Make sure the server is running on the given port. - -    Attempt to connect to given local port. Upon success, assume that the -    events server has already been started. Upon failure, start events server. - -    @param port: the port in which server should be listening -    @type port: int - -    @return: the daemon instance or nothing -    @rtype: EventsServerDaemon or None -    """ -    try: -        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -        s.connect(('localhost', port)) -        s.close() -        logger.info('Server is already running on port %d.', port) -        return None -    except socket.error: -        logger.info('Launching server on port %d.', port) -        return EventsServerDaemon.ensure(port) - - -class EventsServerService(proto.EventsServerService): -    """ -    Service for receiving events in components. -    """ - -    def register(self, controller, request, done): -        """ -        Register a component port to be signaled when specific events come in. - -        @param controller: used to mediate a single method call -        @type controller: protobuf.socketrpc.controller.SocketRpcController -        @param request: the request received from the component -        @type request: leap.common.events.events_pb2.RegisterRequest -        @param done: callback to be called when done -        @type done: protobuf.socketrpc.server.Callback -        """ -        logger.info("Received registration request: %s" % str(request)) -        # add component port to signal list -        if request.event not in registered_components: -            registered_components[request.event] = set([]) -        registered_components[request.event].add(request.port) -        # send response back to component - -        logger.debug('sending response back') -        response = proto.EventResponse() -        response.status = proto.EventResponse.OK -        done.run(response) - -    def signal(self, controller, request, done): -        """ -        Perform an RPC call to signal all components registered to receive a -        specific signal. - -        @param controller: used to mediate a single method call -        @type controller: protobuf.socketrpc.controller.SocketRpcController -        @param request: the request received from the component -        @type request: leap.common.events.events_pb2.SignalRequest -        @param done: callback to be called when done -        @type done: protobuf.socketrpc.server.Callback -        """ -        logger.info('Received signal from component: %s', str(request)) -        # send signal to all registered components -        # TODO: verify signal auth -        if request.event in registered_components: -            for port in registered_components[request.event]: - -                def callback(req, resp): -                    logger.info("Signal received by " + str(port)) - -                service = RpcService(proto.EventsComponentService_Stub, -                                     port, 'localhost') -                service.signal(request, callback=callback) -        # send response back to component -        response = proto.EventResponse() -        response.status = proto.EventResponse.OK -        done.run(response) - - -class EventsServerDaemon(daemon.EventsSingletonDaemon): -    """ -    Singleton class for starting an events server daemon. -    """ - -    @classmethod -    def ensure(cls, port): -        """ -        Make sure the daemon is running on the given port. - -        @param port: the port in which the daemon should listen -        @type port: int - -        @return: a daemon instance -        @rtype: EventsServerDaemon -        """ -        return cls.ensure_service(port, EventsServerService()) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/files.py b/debian/python-leap.common/usr/share/pyshared/leap/common/files.py deleted file mode 100644 index 4c443dd..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/files.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- -# files.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. -""" -Implements file helper methods -""" - -import errno -import logging -import os -import stat -import time - -logger = logging.getLogger(__name__) - - -def check_and_fix_urw_only(cert): -    """ -    Test for 600 mode and try to set it if anything different found - -    Might raise OSError - -    @param cert: Certificate path -    @type cert: str -    """ -    mode = stat.S_IMODE(os.stat(cert).st_mode) - -    if mode != int('600', 8): -        try: -            logger.warning('Bad permission on %s attempting to set 600' % -                           (cert,)) -            os.chmod(cert, stat.S_IRUSR | stat.S_IWUSR) -        except OSError: -            logger.error('Error while trying to chmod 600 %s' % -                         cert) -            raise - - -def get_mtime(filename): -    """ -    Returns the modified time or None if the file doesn't exist - -    @param filename: path to check -    @type filename: str - -    @rtype: str -    """ -    try: -        mtime = time.ctime(os.path.getmtime(filename)) + " GMT" -        return mtime -    except OSError: -        return None - - -def mkdir_p(path): -    """ -    Creates the path and all the intermediate directories that don't -    exist - -    Might raise OSError - -    @param path: path to create -    @type path: str -    """ -    try: -        os.makedirs(path) -    except OSError as exc: -        if exc.errno == errno.EEXIST and os.path.isdir(path): -            pass -        else: -            raise - - -# Twisted implementation of which -def which(name, flags=os.X_OK, path_extension="/usr/sbin:/sbin"): -    """ -    Search PATH for executable files with the given name. - -    On newer versions of MS-Windows, the PATHEXT environment variable will be -    set to the list of file extensions for files considered executable. This -    will normally include things like ".EXE". This fuction will also find files -    with the given name ending with any of these extensions. - -    On MS-Windows the only flag that has any meaning is os.F_OK. Any other -    flags will be ignored. - -    @type name: C{str} -    @param name: The name for which to search. - -    @type flags: C{int} -    @param flags: Arguments to L{os.access}. - -    @rtype: C{list} -    @param: A list of the full paths to files found, in the -    order in which they were found. -    """ - -    result = [] -    exts = filter(None, os.environ.get('PATHEXT', '').split(os.pathsep)) -    path = os.environ.get('PATH', None) -    path = path_extension + os.pathsep + path -    if path is None: -        return [] -    parts = path.split(os.pathsep) -    for p in parts: -        p = os.path.join(p, name) -        if os.access(p, flags): -            result.append(p) -        for e in exts: -            pext = p + e -            if os.access(pext, flags): -                result.append(pext) -    return result diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/__init__.py b/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/__init__.py deleted file mode 100644 index d6dbb8a..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/__init__.py +++ /dev/null @@ -1,286 +0,0 @@ -# -*- coding: utf-8 -*- -# __init__.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -""" -Key Manager is a Nicknym agent for LEAP client. -""" - -import requests - -try: -    import simplejson as json -except ImportError: -    import json  # noqa - -from leap.common.check import leap_assert -from leap.common.keymanager.errors import ( -    KeyNotFound, -    NoPasswordGiven, -) -from leap.common.keymanager.keys import ( -    build_key_from_dict, -) -from leap.common.keymanager.openpgp import ( -    OpenPGPKey, -    OpenPGPScheme, -    encrypt_sym, -) - - -TAGS_INDEX = 'by-tags' -TAGS_AND_PRIVATE_INDEX = 'by-tags-and-private' -INDEXES = { -    TAGS_INDEX: ['tags'], -    TAGS_AND_PRIVATE_INDEX: ['tags', 'bool(private)'], -} - - -class KeyManager(object): - -    def __init__(self, address, nickserver_url, soledad, token=None): -        """ -        Initialize a Key Manager for user's C{address} with provider's -        nickserver reachable in C{url}. - -        @param address: The address of the user of this Key Manager. -        @type address: str -        @param url: The URL of the nickserver. -        @type url: str -        @param soledad: A Soledad instance for local storage of keys. -        @type soledad: leap.soledad.Soledad -        """ -        self._address = address -        self._nickserver_url = nickserver_url -        self._soledad = soledad -        self.token = token -        self._wrapper_map = { -            OpenPGPKey: OpenPGPScheme(soledad), -            # other types of key will be added to this mapper. -        } -        self._init_indexes() -        self._fetcher = requests - -    # -    # utilities -    # - -    def _key_class_from_type(self, ktype): -        """ -        Return key class from string representation of key type. -        """ -        return filter( -            lambda klass: str(klass) == ktype, -            self._wrapper_map).pop() - -    def _init_indexes(self): -        """ -        Initialize the database indexes. -        """ -        # Ask the database for currently existing indexes. -        db_indexes = dict(self._soledad.list_indexes()) -        # Loop through the indexes we expect to find. -        for name, expression in INDEXES.items(): -            if name not in db_indexes: -                # The index does not yet exist. -                self._soledad.create_index(name, *expression) -                continue -            if expression == db_indexes[name]: -                # The index exists and is up to date. -                continue -            # The index exists but the definition is not what expected, so we -            # delete it and add the proper index expression. -            self._soledad.delete_index(name) -            self._soledad.create_index(name, *expression) - -    def _get_dict_from_http_json(self, path): -        """ -        Make a GET HTTP request and return a dictionary containing the -        response. -        """ -        response = self._fetcher.get(self._nickserver_url+path) -        leap_assert(response.status_code == 200, 'Invalid response.') -        leap_assert( -            response.headers['content-type'].startswith('application/json') -                is True, -            'Content-type is not JSON.') -        return response.json() - -    # -    # key management -    # - -    def send_key(self, ktype, send_private=False, password=None): -        """ -        Send user's key of type C{ktype} to provider. - -        Public key bound to user's is sent to provider, which will sign it and -        replace any prior keys for the same address in its database. - -        If C{send_private} is True, then the private key is encrypted with -        C{password} and sent to server in the same request, together with a -        hash string of user's address and password. The encrypted private key -        will be saved in the server in a way it is publicly retrievable -        through the hash string. - -        @param ktype: The type of the key. -        @type ktype: KeyType - -        @raise httplib.HTTPException: -        @raise KeyNotFound: If the key was not found both locally and in -            keyserver. -        """ -        # prepare the public key bound to address -        pubkey = self.get_key( -            self._address, ktype, private=False, fetch_remote=False) -        data = { -            'address': self._address, -            'keys': [ -                json.loads(pubkey.get_json()), -            ] -        } -        # prepare the private key bound to address -        if send_private: -            if password is None or password == '': -                raise NoPasswordGiven('Can\'t send unencrypted private keys!') -            privkey = self.get_key( -                self._address, ktype, private=True, fetch_remote=False) -            privkey = json.loads(privkey.get_json()) -            privkey.key_data = encrypt_sym(privkey.key_data, password) -            data['keys'].append(privkey) -        self._fetcher.put( -            self._nickserver_url + '/key/' + self._address, -            data=data, -            auth=(self._address, self._token)) - -    def get_key(self, address, ktype, private=False, fetch_remote=True): -        """ -        Return a key of type C{ktype} bound to C{address}. - -        First, search for the key in local storage. If it is not available, -        then try to fetch from nickserver. - -        @param address: The address bound to the key. -        @type address: str -        @param ktype: The type of the key. -        @type ktype: KeyType -        @param private: Look for a private key instead of a public one? -        @type private: bool - -        @return: A key of type C{ktype} bound to C{address}. -        @rtype: EncryptionKey -        @raise KeyNotFound: If the key was not found both locally and in -            keyserver. -        """ -        leap_assert( -            ktype in self._wrapper_map, -            'Unkown key type: %s.' % str(ktype)) -        try: -            return self._wrapper_map[ktype].get_key(address, private=private) -        except KeyNotFound: -            if fetch_remote is False: -                raise -            # fetch keys from server and discard unwanted types. -            keys = filter(lambda k: isinstance(k, ktype), -                          self.fetch_keys_from_server(address)) -            if len(keys) is 0: -                raise KeyNotFound() -            leap_assert( -                len(keys) == 1, -                'Got more than one key of type %s for %s.' % -                (str(ktype), address)) -            self._wrapper_map[ktype].put_key(keys[0]) -            return self._wrapper_map[ktype].get_key(address, private=private) - -    def fetch_keys_from_server(self, address): -        """ -        Fetch keys bound to C{address} from nickserver. - -        @param address: The address bound to the keys. -        @type address: str - -        @return: A list of keys bound to C{address}. -        @rtype: list of EncryptionKey -        @raise KeyNotFound: If the key was not found on nickserver. -        @raise httplib.HTTPException: -        """ -        keydata = self._get_dict_from_http_json('/key/%s' % address) -        leap_assert( -            keydata['address'] == address, -            "Fetched key for wrong address.") -        keys = [] -        for key in keydata['keys']: -            keys.append( -                build_key_from_dict( -                    self._key_class_from_type(key['type']), -                    address, -                    key)) -        return keys - -    def get_all_keys_in_local_db(self, private=False): -        """ -        Return all keys stored in local database. - -        @return: A list with all keys in local db. -        @rtype: list -        """ -        return map( -            lambda doc: build_key_from_dict( -                self._key_class_from_type(doc.content['type']), -                doc.content['address'], -                doc.content), -            self._soledad.get_from_index( -                TAGS_AND_PRIVATE_INDEX, -                'keymanager-key', -                '1' if private else '0')) - -    def refresh_keys(self): -        """ -        Fetch keys from nickserver and update them locally. -        """ -        addresses = set(map( -            lambda doc: doc.address, -            self.get_all_keys_in_local_db(private=False))) -        # TODO: maybe we should not attempt to refresh our own public key? -        for address in addresses: -            for key in self.fetch_keys_from_server(address): -                self._wrapper_map[key.__class__].put_key(key) - -    def gen_key(self, ktype): -        """ -        Generate a key of type C{ktype} bound to the user's address. - -        @param ktype: The type of the key. -        @type ktype: KeyType - -        @return: The generated key. -        @rtype: EncryptionKey -        """ -        return self._wrapper_map[ktype].gen_key(self._address) - -    # -    # Token setter/getter -    # - -    def _get_token(self): -        return self._token - -    def _set_token(self, token): -        self._token = token - -    token = property( -        _get_token, _set_token, doc='The auth token.') diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/errors.py b/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/errors.py deleted file mode 100644 index 1cf506e..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/errors.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# errors.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -""" -Errors and exceptions used by the Key Manager. -""" - - -class KeyNotFound(Exception): -    """ -    Raised when key was no found on keyserver. -    """ - - -class KeyAlreadyExists(Exception): -    """ -    Raised when attempted to create a key that already exists. -    """ - - -class KeyAttributesDiffer(Exception): -    """ -    Raised when trying to delete a key but the stored key differs from the key -    passed to the delete_key() method. -    """ - -class NoPasswordGiven(Exception): -    """ -    Raised when trying to perform some action that needs a password without -    providing one. -    """ diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/gpg.py b/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/gpg.py deleted file mode 100644 index f3e6453..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/gpg.py +++ /dev/null @@ -1,397 +0,0 @@ -# -*- coding: utf-8 -*- -# gpgwrapper.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -""" -A GPG wrapper used to handle OpenPGP keys. - -This is a temporary class that will be superseded by the a revised version of -python-gnupg. -""" - - -import os -import gnupg -import re -from gnupg import ( -    logger, -    _is_sequence, -    _make_binary_stream, -) - - -class ListPackets(): -    """ -    Handle status messages for --list-packets. -    """ - -    def __init__(self, gpg): -        """ -        Initialize the packet listing handling class. - -        @param gpg: GPG object instance. -        @type gpg: gnupg.GPG -        """ -        self.gpg = gpg -        self.nodata = None -        self.key = None -        self.need_passphrase = None -        self.need_passphrase_sym = None -        self.userid_hint = None - -    def handle_status(self, key, value): -        """ -        Handle one line of the --list-packets status message. - -        @param key: The status message key. -        @type key: str -        @param value: The status message value. -        @type value: str -        """ -        # TODO: write tests for handle_status -        if key == 'NODATA': -            self.nodata = True -        if key == 'ENC_TO': -            # This will only capture keys in our keyring. In the future we -            # may want to include multiple unknown keys in this list. -            self.key, _, _ = value.split() -        if key == 'NEED_PASSPHRASE': -            self.need_passphrase = True -        if key == 'NEED_PASSPHRASE_SYM': -            self.need_passphrase_sym = True -        if key == 'USERID_HINT': -            self.userid_hint = value.strip().split() - - -class GPGWrapper(gnupg.GPG): -    """ -    This is a temporary class for handling GPG requests, and should be -    replaced by a more general class used throughout the project. -    """ - -    GNUPG_HOME = os.environ['HOME'] + "/.config/leap/gnupg" -    GNUPG_BINARY = "/usr/bin/gpg"  # this has to be changed based on OS - -    def __init__(self, gpgbinary=GNUPG_BINARY, gnupghome=GNUPG_HOME, -                 verbose=False, use_agent=False, keyring=None, options=None): -        """ -        Initialize a GnuPG process wrapper. - -        @param gpgbinary: Name for GnuPG binary executable. -        @type gpgbinary: C{str} -        @param gpghome: Full pathname to directory containing the public and -            private keyrings. -        @type gpghome: C{str} -        @param keyring: Name of alternative keyring file to use. If specified, -            the default keyring is not used. -        @param verbose: Should some verbose info be output? -        @type verbose: bool -        @param use_agent: Should pass `--use-agent` to GPG binary? -        @type use_agent: bool -        @param keyring: Path for the keyring to use. -        @type keyring: str -        @options: A list of additional options to pass to the GPG binary. -        @type options: list - -        @raise: RuntimeError with explanation message if there is a problem -            invoking gpg. -        """ -        gnupg.GPG.__init__(self, gnupghome=gnupghome, gpgbinary=gpgbinary, -                           verbose=verbose, use_agent=use_agent, -                           keyring=keyring, options=options) -        self.result_map['list-packets'] = ListPackets - -    def find_key_by_email(self, email, secret=False): -        """ -        Find user's key based on their email. - -        @param email: Email address of key being searched for. -        @type email: str -        @param secret: Should we search for a secret key? -        @type secret: bool - -        @return: The fingerprint of the found key. -        @rtype: str -        """ -        for key in self.list_keys(secret=secret): -            for uid in key['uids']: -                if re.search(email, uid): -                    return key -        raise LookupError("GnuPG public key for email %s not found!" % email) - -    def find_key_by_subkey(self, subkey, secret=False): -        """ -        Find user's key based on a subkey fingerprint. - -        @param email: Subkey fingerprint of the key being searched for. -        @type email: str -        @param secret: Should we search for a secret key? -        @type secret: bool - -        @return: The fingerprint of the found key. -        @rtype: str -        """ -        for key in self.list_keys(secret=secret): -            for sub in key['subkeys']: -                if sub[0] == subkey: -                    return key -        raise LookupError( -            "GnuPG public key for subkey %s not found!" % subkey) - -    def find_key_by_keyid(self, keyid, secret=False): -        """ -        Find user's key based on the key ID. - -        @param email: The key ID of the key being searched for. -        @type email: str -        @param secret: Should we search for a secret key? -        @type secret: bool - -        @return: The fingerprint of the found key. -        @rtype: str -        """ -        for key in self.list_keys(secret=secret): -            if keyid == key['keyid']: -                return key -        raise LookupError( -            "GnuPG public key for keyid %s not found!" % keyid) - -    def find_key_by_fingerprint(self, fingerprint, secret=False): -        """ -        Find user's key based on the key fingerprint. - -        @param email: The fingerprint of the key being searched for. -        @type email: str -        @param secret: Should we search for a secret key? -        @type secret: bool - -        @return: The fingerprint of the found key. -        @rtype: str -        """ -        for key in self.list_keys(secret=secret): -            if fingerprint == key['fingerprint']: -                return key -        raise LookupError( -            "GnuPG public key for fingerprint %s not found!" % fingerprint) - -    def encrypt(self, data, recipient, sign=None, always_trust=True, -                passphrase=None, symmetric=False): -        """ -        Encrypt data using GPG. - -        @param data: The data to be encrypted. -        @type data: str -        @param recipient: The address of the public key to be used. -        @type recipient: str -        @param sign: Should the encrypted content be signed? -        @type sign: bool -        @param always_trust: Skip key validation and assume that used keys -            are always fully trusted? -        @type always_trust: bool -        @param passphrase: The passphrase to be used if symmetric encryption -            is desired. -        @type passphrase: str -        @param symmetric: Should we encrypt to a password? -        @type symmetric: bool - -        @return: An object with encrypted result in the `data` field. -        @rtype: gnupg.Crypt -        """ -        # TODO: devise a way so we don't need to "always trust". -        return gnupg.GPG.encrypt(self, data, recipient, sign=sign, -                                 always_trust=always_trust, -                                 passphrase=passphrase, -                                 symmetric=symmetric, -                                 cipher_algo='AES256') - -    def decrypt(self, data, always_trust=True, passphrase=None): -        """ -        Decrypt data using GPG. - -        @param data: The data to be decrypted. -        @type data: str -        @param always_trust: Skip key validation and assume that used keys -            are always fully trusted? -        @type always_trust: bool -        @param passphrase: The passphrase to be used if symmetric encryption -            is desired. -        @type passphrase: str - -        @return: An object with decrypted result in the `data` field. -        @rtype: gnupg.Crypt -        """ -        # TODO: devise a way so we don't need to "always trust". -        return gnupg.GPG.decrypt(self, data, always_trust=always_trust, -                                 passphrase=passphrase) - -    def send_keys(self, keyserver, *keyids): -        """ -        Send keys to a keyserver - -        @param keyserver: The keyserver to send the keys to. -        @type keyserver: str -        @param keyids: The key ids to send. -        @type keyids: list - -        @return: A list of keys sent to server. -        @rtype: gnupg.ListKeys -        """ -        # TODO: write tests for this. -        # TODO: write a SendKeys class to handle status for this. -        result = self.result_map['list'](self) -        gnupg.logger.debug('send_keys: %r', keyids) -        data = gnupg._make_binary_stream("", self.encoding) -        args = ['--keyserver', keyserver, '--send-keys'] -        args.extend(keyids) -        self._handle_io(args, data, result, binary=True) -        gnupg.logger.debug('send_keys result: %r', result.__dict__) -        data.close() -        return result - -    def encrypt_file(self, file, recipients, sign=None, -                     always_trust=False, passphrase=None, -                     armor=True, output=None, symmetric=False, -                     cipher_algo=None): -        """ -        Encrypt the message read from the file-like object 'file'. - -        @param file: The file to be encrypted. -        @type data: file -        @param recipient: The address of the public key to be used. -        @type recipient: str -        @param sign: Should the encrypted content be signed? -        @type sign: bool -        @param always_trust: Skip key validation and assume that used keys -            are always fully trusted? -        @type always_trust: bool -        @param passphrase: The passphrase to be used if symmetric encryption -            is desired. -        @type passphrase: str -        @param armor: Create ASCII armored output? -        @type armor: bool -        @param output: Path of file to write results in. -        @type output: str -        @param symmetric: Should we encrypt to a password? -        @type symmetric: bool -        @param cipher_algo: Algorithm to use. -        @type cipher_algo: str - -        @return: An object with encrypted result in the `data` field. -        @rtype: gnupg.Crypt -        """ -        args = ['--encrypt'] -        if symmetric: -            args = ['--symmetric'] -            if cipher_algo: -                args.append('--cipher-algo %s' % cipher_algo) -        else: -            args = ['--encrypt'] -            if not _is_sequence(recipients): -                recipients = (recipients,) -            for recipient in recipients: -                args.append('--recipient "%s"' % recipient) -        if armor:  # create ascii-armored output - set to False for binary -            args.append('--armor') -        if output:  # write the output to a file with the specified name -            if os.path.exists(output): -                os.remove(output)  # to avoid overwrite confirmation message -            args.append('--output "%s"' % output) -        if sign: -            args.append('--sign --default-key "%s"' % sign) -        if always_trust: -            args.append("--always-trust") -        result = self.result_map['crypt'](self) -        self._handle_io(args, file, result, passphrase=passphrase, binary=True) -        logger.debug('encrypt result: %r', result.data) -        return result - -    def list_packets(self, data): -        """ -        List the sequence of packets. - -        @param data: The data to extract packets from. -        @type data: str - -        @return: An object with packet info. -        @rtype ListPackets -        """ -        args = ["--list-packets"] -        result = self.result_map['list-packets'](self) -        self._handle_io( -            args, -            _make_binary_stream(data, self.encoding), -            result, -        ) -        return result - -    def encrypted_to(self, data): -        """ -        Return the key to which data is encrypted to. - -        @param data: The data to be examined. -        @type data: str - -        @return: The fingerprint of the key to which data is encrypted to. -        @rtype: str -        """ -        # TODO: make this support multiple keys. -        result = self.list_packets(data) -        if not result.key: -            raise LookupError( -                "Content is not encrypted to a GnuPG key!") -        try: -            return self.find_key_by_keyid(result.key) -        except: -            return self.find_key_by_subkey(result.key) - -    def is_encrypted_sym(self, data): -        """ -        Say whether some chunk of data is encrypted to a symmetric key. - -        @param data: The data to be examined. -        @type data: str - -        @return: Whether data is encrypted to a symmetric key. -        @rtype: bool -        """ -        result = self.list_packets(data) -        return bool(result.need_passphrase_sym) - -    def is_encrypted_asym(self, data): -        """ -        Say whether some chunk of data is encrypted to a private key. - -        @param data: The data to be examined. -        @type data: str - -        @return: Whether data is encrypted to a private key. -        @rtype: bool -        """ -        result = self.list_packets(data) -        return bool(result.key) - -    def is_encrypted(self, data): -        """ -        Say whether some chunk of data is encrypted to a key. - -        @param data: The data to be examined. -        @type data: str - -        @return: Whether data is encrypted to a key. -        @rtype: bool -        """ -        return self.is_encrypted_asym(data) or self.is_encrypted_sym(data) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/keys.py b/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/keys.py deleted file mode 100644 index 2e6bfe9..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/keys.py +++ /dev/null @@ -1,230 +0,0 @@ -# -*- coding: utf-8 -*- -# keys.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -""" -Abstact key type and encryption scheme representations. -""" - - -try: -    import simplejson as json -except ImportError: -    import json  # noqa -import re - - -from hashlib import sha256 -from abc import ABCMeta, abstractmethod -from leap.common.check import leap_assert - - -# -# Key handling utilities -# - -def is_address(address): -    """ -    Return whether the given C{address} is in the form user@provider. - -    @param address: The address to be tested. -    @type address: str -    @return: Whether C{address} is in the form user@provider. -    @rtype: bool -    """ -    return bool(re.match('[\w.-]+@[\w.-]+', address)) - - -def build_key_from_dict(kClass, address, kdict): -    """ -    Build an C{kClass} key bound to C{address} based on info in C{kdict}. - -    @param address: The address bound to the key. -    @type address: str -    @param kdict: Dictionary with key data. -    @type kdict: dict -    @return: An instance of the key. -    @rtype: C{kClass} -    """ -    leap_assert(address == kdict['address'], 'Wrong address in key data.') -    return kClass( -        address, -        key_id=kdict['key_id'], -        fingerprint=kdict['fingerprint'], -        key_data=kdict['key_data'], -        private=kdict['private'], -        length=kdict['length'], -        expiry_date=kdict['expiry_date'], -        first_seen_at=kdict['first_seen_at'], -        last_audited_at=kdict['last_audited_at'], -        validation=kdict['validation'],  # TODO: verify for validation. -    ) - - -def keymanager_doc_id(ktype, address, private=False): -    """ -    Return the document id for the document containing a key for -    C{address}. - -    @param address: The type of the key. -    @type address: KeyType -    @param address: The address bound to the key. -    @type address: str -    @param private: Whether the key is private or not. -    @type private: bool -    @return: The document id for the document that stores a key bound to -        C{address}. -    @rtype: str -    """ -    leap_assert(is_address(address), "Wrong address format: %s" % address) -    ktype = str(ktype) -    visibility = 'private' if private else 'public' -    return sha256('keymanager-'+address+'-'+ktype+'-'+visibility).hexdigest() - - -# -# Abstraction for encryption keys -# - -class EncryptionKey(object): -    """ -    Abstract class for encryption keys. - -    A key is "validated" if the nicknym agent has bound the user address to a -    public key. Nicknym supports three different levels of key validation: - -    * Level 3 - path trusted: A path of cryptographic signatures can be traced -      from a trusted key to the key under evaluation. By default, only the -      provider key from the user's provider is a "trusted key". -    * level 2 - provider signed: The key has been signed by a provider key for -      the same domain, but the provider key is not validated using a trust -      path (i.e. it is only registered) -    * level 1 - registered: The key has been encountered and saved, it has no -      signatures (that are meaningful to the nicknym agent). -    """ - -    __metaclass__ = ABCMeta - -    def __init__(self, address, key_id=None, fingerprint=None, -                 key_data=None, private=None, length=None, expiry_date=None, -                 validation=None, first_seen_at=None, last_audited_at=None): -        self.address = address -        self.key_id = key_id -        self.fingerprint = fingerprint -        self.key_data = key_data -        self.private = private -        self.length = length -        self.expiry_date = expiry_date -        self.validation = validation -        self.first_seen_at = first_seen_at -        self.last_audited_at = last_audited_at - -    def get_json(self): -        """ -        Return a JSON string describing this key. - -        @return: The JSON string describing this key. -        @rtype: str -        """ -        return json.dumps({ -            'address': self.address, -            'type': str(self.__class__), -            'key_id': self.key_id, -            'fingerprint': self.fingerprint, -            'key_data': self.key_data, -            'private': self.private, -            'length': self.length, -            'expiry_date': self.expiry_date, -            'validation': self.validation, -            'first_seen_at': self.first_seen_at, -            'last_audited_at': self.last_audited_at, -            'tags': ['keymanager-key'], -        }) - - -# -# Encryption schemes -# - -class EncryptionScheme(object): -    """ -    Abstract class for Encryption Schemes. - -    A wrapper for a certain encryption schemes should know how to get and put -    keys in local storage using Soledad, how to generate new keys and how to -    find out about possibly encrypted content. -    """ - -    __metaclass__ = ABCMeta - -    def __init__(self, soledad): -        """ -        Initialize this Encryption Scheme. - -        @param soledad: A Soledad instance for local storage of keys. -        @type soledad: leap.soledad.Soledad -        """ -        self._soledad = soledad - -    @abstractmethod -    def get_key(self, address, private=False): -        """ -        Get key from local storage. - -        @param address: The address bound to the key. -        @type address: str -        @param private: Look for a private key instead of a public one? -        @type private: bool - -        @return: The key bound to C{address}. -        @rtype: EncryptionKey -        @raise KeyNotFound: If the key was not found on local storage. -        """ -        pass - -    @abstractmethod -    def put_key(self, key): -        """ -        Put a key in local storage. - -        @param key: The key to be stored. -        @type key: EncryptionKey -        """ -        pass - -    @abstractmethod -    def gen_key(self, address): -        """ -        Generate a new key. - -        @param address: The address bound to the key. -        @type address: str - -        @return: The key bound to C{address}. -        @rtype: EncryptionKey -        """ -        pass - -    @abstractmethod -    def delete_key(self, key): -        """ -        Remove C{key} from storage. - -        @param key: The key to be removed. -        @type key: EncryptionKey -        """ -        pass diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/openpgp.py b/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/openpgp.py deleted file mode 100644 index e2ffe76..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/openpgp.py +++ /dev/null @@ -1,459 +0,0 @@ -# -*- coding: utf-8 -*- -# openpgp.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -""" -Infrastructure for using OpenPGP keys in Key Manager. -""" - - -import re -import tempfile -import shutil - -from leap.common.check import leap_assert -from leap.common.keymanager.errors import ( -    KeyNotFound, -    KeyAlreadyExists, -    KeyAttributesDiffer -) -from leap.common.keymanager.keys import ( -    EncryptionKey, -    EncryptionScheme, -    is_address, -    keymanager_doc_id, -    build_key_from_dict, -) -from leap.common.keymanager.gpg import GPGWrapper - - -# -# Utility functions -# - -def encrypt_sym(data, passphrase): -    """ -    Encrypt C{data} with C{passphrase}. - -    @param data: The data to be encrypted. -    @type data: str -    @param passphrase: The passphrase used to encrypt C{data}. -    @type passphrase: str - -    @return: The encrypted data. -    @rtype: str -    """ - -    def _encrypt_cb(gpg): -        return gpg.encrypt( -                data, None, passphrase=passphrase, symmetric=True).data - -    return _safe_call(_encrypt_cb) - - -def decrypt_sym(data, passphrase): -    """ -    Decrypt C{data} with C{passphrase}. - -    @param data: The data to be decrypted. -    @type data: str -    @param passphrase: The passphrase used to decrypt C{data}. -    @type passphrase: str - -    @return: The decrypted data. -    @rtype: str -    """ - -    def _decrypt_cb(gpg): -        return gpg.decrypt(data, passphrase=passphrase).data - -    return _safe_call(_decrypt_cb) - - -def encrypt_asym(data, key): -    """ -    Encrypt C{data} using public @{key}. - -    @param data: The data to be encrypted. -    @type data: str -    @param key: The key used to encrypt. -    @type key: OpenPGPKey - -    @return: The encrypted data. -    @rtype: str -    """ -    leap_assert(key.private is False, 'Key is not public.') - -    def _encrypt_cb(gpg): -        return gpg.encrypt( -                data, key.fingerprint, symmetric=False).data - -    return _safe_call(_encrypt_cb, key.key_data) - - -def decrypt_asym(data, key): -    """ -    Decrypt C{data} using private @{key}. - -    @param data: The data to be decrypted. -    @type data: str -    @param key: The key used to decrypt. -    @type key: OpenPGPKey - -    @return: The decrypted data. -    @rtype: str -    """ -    leap_assert(key.private is True, 'Key is not private.') - -    def _decrypt_cb(gpg): -        return gpg.decrypt(data).data - -    return _safe_call(_decrypt_cb, key.key_data) - - -def is_encrypted(data): -    """ -    Return whether C{data} was encrypted using OpenPGP. - -    @param data: The data we want to know about. -    @type data: str - -    @return: Whether C{data} was encrypted using this wrapper. -    @rtype: bool -    """ - -    def _is_encrypted_cb(gpg): -        return gpg.is_encrypted(data) - -    return _safe_call(_is_encrypted_cb) - - -def is_encrypted_sym(data): -    """ -    Return whether C{data} was encrypted using a public OpenPGP key. - -    @param data: The data we want to know about. -    @type data: str - -    @return: Whether C{data} was encrypted using this wrapper. -    @rtype: bool -    """ - -    def _is_encrypted_cb(gpg): -        return gpg.is_encrypted_sym(data) - -    return _safe_call(_is_encrypted_cb) - - -def is_encrypted_asym(data): -    """ -    Return whether C{data} was asymmetrically encrypted using OpenPGP. - -    @param data: The data we want to know about. -    @type data: str - -    @return: Whether C{data} was encrypted using this wrapper. -    @rtype: bool -    """ - -    def _is_encrypted_cb(gpg): -        return gpg.is_encrypted_asym(data) - -    return _safe_call(_is_encrypted_cb) - - -def _build_key_from_gpg(address, key, key_data): -    """ -    Build an OpenPGPKey for C{address} based on C{key} from -    local gpg storage. - -    ASCII armored GPG key data has to be queried independently in this -    wrapper, so we receive it in C{key_data}. - -    @param address: The address bound to the key. -    @type address: str -    @param key: Key obtained from GPG storage. -    @type key: dict -    @param key_data: Key data obtained from GPG storage. -    @type key_data: str -    @return: An instance of the key. -    @rtype: OpenPGPKey -    """ -    return OpenPGPKey( -        address, -        key_id=key['keyid'], -        fingerprint=key['fingerprint'], -        key_data=key_data, -        private=True if key['type'] == 'sec' else False, -        length=key['length'], -        expiry_date=key['expires'], -        validation=None,  # TODO: verify for validation. -    ) - - -def _build_unitary_gpgwrapper(key_data=None): -    """ -    Return a temporary GPG wrapper keyring containing exactly zero or one -    keys. - -    Temporary unitary keyrings allow the to use GPG's facilities for exactly -    one key. This function creates an empty temporary keyring and imports -    C{key_data} if it is not None. - -    @param key_data: ASCII armored key data. -    @type key_data: str -    @return: A GPG wrapper with a unitary keyring. -    @rtype: gnupg.GPG -    """ -    tmpdir = tempfile.mkdtemp() -    gpg = GPGWrapper(gnupghome=tmpdir) -    leap_assert(len(gpg.list_keys()) is 0, 'Keyring not empty.') -    if key_data: -        gpg.import_keys(key_data) -        leap_assert( -            len(gpg.list_keys()) is 1, -            'Unitary keyring has wrong number of keys: %d.' -            % len(gpg.list_keys())) -    return gpg - - -def _destroy_unitary_gpgwrapper(gpg): -    """ -    Securely erase a unitary keyring. - -    @param gpg: A GPG wrapper instance. -    @type gpg: gnupg.GPG -    """ -    for secret in [True, False]: -        for key in gpg.list_keys(secret=secret): -            gpg.delete_keys( -                key['fingerprint'], -                secret=secret) -    leap_assert(len(gpg.list_keys()) is 0, 'Keyring not empty!') -    # TODO: implement some kind of wiping of data or a more secure way that -    # does not write to disk. -    shutil.rmtree(gpg.gnupghome) - - -def _safe_call(callback, key_data=None, **kwargs): -    """ -    Run C{callback} in an unitary keyring containing C{key_data}. - -    @param callback: Function whose first argument is the gpg keyring. -    @type callback: function(gnupg.GPG) -    @param key_data: ASCII armored key data. -    @type key_data: str -    @param **kwargs: Other eventual parameters for the callback. -    @type **kwargs: **dict - -    @return: The results of the callback. -    @rtype: str or bool -    """ -    gpg = _build_unitary_gpgwrapper(key_data) -    val = callback(gpg, **kwargs) -    _destroy_unitary_gpgwrapper(gpg) -    return val - - -# -# The OpenPGP wrapper -# - -class OpenPGPKey(EncryptionKey): -    """ -    Base class for OpenPGP keys. -    """ - - -class OpenPGPScheme(EncryptionScheme): -    """ -    A wrapper for OpenPGP keys. -    """ - -    def __init__(self, soledad): -        """ -        Initialize the OpenPGP wrapper. - -        @param soledad: A Soledad instance for key storage. -        @type soledad: leap.soledad.Soledad -        """ -        EncryptionScheme.__init__(self, soledad) - -    def gen_key(self, address): -        """ -        Generate an OpenPGP keypair bound to C{address}. - -        @param address: The address bound to the key. -        @type address: str -        @return: The key bound to C{address}. -        @rtype: OpenPGPKey -        @raise KeyAlreadyExists: If key already exists in local database. -        """ -        # make sure the key does not already exist -        leap_assert(is_address(address), 'Not an user address: %s' % address) -        try: -            self.get_key(address) -            raise KeyAlreadyExists(address) -        except KeyNotFound: -            pass - -        def _gen_key_cb(gpg): -            params = gpg.gen_key_input( -                key_type='RSA', -                key_length=4096, -                name_real=address, -                name_email=address, -                name_comment='Generated by LEAP Key Manager.') -            gpg.gen_key(params) -            pubkeys = gpg.list_keys() -            # assert for new key characteristics -            leap_assert( -                len(pubkeys) is 1,  # a unitary keyring! -                'Keyring has wrong number of keys: %d.' % len(pubkeys)) -            key = gpg.list_keys(secret=True).pop() -            leap_assert( -                len(key['uids']) is 1,  # with just one uid! -                'Wrong number of uids for key: %d.' % len(key['uids'])) -            leap_assert( -                re.match('.*<%s>$' % address, key['uids'][0]) is not None, -                'Key not correctly bound to address.') -            # insert both public and private keys in storage -            for secret in [True, False]: -                key = gpg.list_keys(secret=secret).pop() -                openpgp_key = _build_key_from_gpg( -                    address, key, -                    gpg.export_keys(key['fingerprint'], secret=secret)) -                self.put_key(openpgp_key) - -        _safe_call(_gen_key_cb) -        return self.get_key(address, private=True) - -    def get_key(self, address, private=False): -        """ -        Get key bound to C{address} from local storage. - -        @param address: The address bound to the key. -        @type address: str -        @param private: Look for a private key instead of a public one? -        @type private: bool - -        @return: The key bound to C{address}. -        @rtype: OpenPGPKey -        @raise KeyNotFound: If the key was not found on local storage. -        """ -        leap_assert(is_address(address), 'Not an user address: %s' % address) -        doc = self._get_key_doc(address, private) -        if doc is None: -            raise KeyNotFound(address) -        return build_key_from_dict(OpenPGPKey, address, doc.content) - -    def put_key_raw(self, data): -        """ -        Put key contained in raw C{data} in local storage. - -        @param data: The key data to be stored. -        @type data: str -        """ -        # TODO: add more checks for correct key data. -        leap_assert(data is not None, 'Data does not represent a key.') - -        def _put_key_raw_cb(gpg): - -            privkey = None -            pubkey = None -            try: -                privkey = gpg.list_keys(secret=True).pop() -            except IndexError: -                pass -            pubkey = gpg.list_keys(secret=False).pop()  # unitary keyring -            # extract adress from first uid on key -            match = re.match('.*<([\w.-]+@[\w.-]+)>.*', pubkey['uids'].pop()) -            leap_assert(match is not None, 'No user address in key data.') -            address = match.group(1) -            if privkey is not None: -                match = re.match( -                    '.*<([\w.-]+@[\w.-]+)>.*', privkey['uids'].pop()) -                leap_assert(match is not None, 'No user address in key data.') -                privaddress = match.group(1) -                leap_assert( -                    address == privaddress, -                    'Addresses in pub and priv key differ.') -                leap_assert( -                    pubkey['fingerprint'] == privkey['fingerprint'], -                    'Fingerprints for pub and priv key differ.') -                # insert private key in storage -                openpgp_privkey = _build_key_from_gpg( -                    address, privkey, -                    gpg.export_keys(privkey['fingerprint'], secret=True)) -                self.put_key(openpgp_privkey) -            # insert public key in storage -            openpgp_pubkey = _build_key_from_gpg( -                address, pubkey, -                gpg.export_keys(pubkey['fingerprint'], secret=False)) -            self.put_key(openpgp_pubkey) - -        _safe_call(_put_key_raw_cb, data) - -    def put_key(self, key): -        """ -        Put C{key} in local storage. - -        @param key: The key to be stored. -        @type key: OpenPGPKey -        """ -        doc = self._get_key_doc(key.address, private=key.private) -        if doc is None: -            self._soledad.create_doc_from_json( -                key.get_json(), -                doc_id=keymanager_doc_id( -                    OpenPGPKey, key.address, key.private)) -        else: -            doc.set_json(key.get_json()) -            self._soledad.put_doc(doc) - -    def _get_key_doc(self, address, private=False): -        """ -        Get the document with a key (public, by default) bound to C{address}. - -        If C{private} is True, looks for a private key instead of a public. - -        @param address: The address bound to the key. -        @type address: str -        @param private: Whether to look for a private key. -        @type private: bool -        @return: The document with the key or None if it does not exist. -        @rtype: leap.soledad.backends.leap_backend.LeapDocument -        """ -        return self._soledad.get_doc( -            keymanager_doc_id(OpenPGPKey, address, private)) - -    def delete_key(self, key): -        """ -        Remove C{key} from storage. - -        @param key: The key to be removed. -        @type key: EncryptionKey -        """ -        leap_assert(key.__class__ is OpenPGPKey, 'Wrong key type.') -        stored_key = self.get_key(key.address, private=key.private) -        if stored_key is None: -            raise KeyNotFound(key) -        if stored_key.__dict__ != key.__dict__: -            raise KeyAttributesDiffer(key) -        doc = self._soledad.get_doc( -            keymanager_doc_id(OpenPGPKey, key.address, key.private)) -        self._soledad.delete_doc(doc) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/__init__.py b/debian/python-leap.common/usr/share/pyshared/leap/common/testing/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/__init__.py +++ /dev/null diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/basetest.py b/debian/python-leap.common/usr/share/pyshared/leap/common/testing/basetest.py deleted file mode 100644 index 65e23a9..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/basetest.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# basetest.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. -""" -Common testing facilities -""" -import os -import platform -import shutil -import tempfile - -try: -    import unittest2 as unittest -except ImportError: -    import unittest - -from leap.common.check import leap_assert -from leap.common.files import mkdir_p, check_and_fix_urw_only - - -class BaseLeapTest(unittest.TestCase): -    """ -    Base Leap TestCase -    """ -    __name__ = "leap_test" -    _system = platform.system() - -    @classmethod -    def setUpClass(cls): -        """ -        Sets up common facilities for testing this TestCase: -        - custom PATH and HOME environmental variables -        - creates a temporal folder to which those point. -        It saves the old path and home vars so they can be restored later. -        """ -        cls.old_path = os.environ['PATH'] -        cls.old_home = os.environ['HOME'] -        cls.tempdir = tempfile.mkdtemp(prefix="leap_tests-") -        cls.home = cls.tempdir -        bin_tdir = os.path.join( -            cls.tempdir, -            'bin') -        os.environ["PATH"] = bin_tdir -        os.environ["HOME"] = cls.tempdir - -    @classmethod -    def tearDownClass(cls): -        """ -        Cleanup common facilities used for testing this TestCase: -        - restores the default PATH and HOME variables -        - removes the temporal folder -        """ -        os.environ["PATH"] = cls.old_path -        os.environ["HOME"] = cls.old_home -        # safety check! please do not wipe my home... -        # XXX needs to adapt to non-linuces -        leap_assert( -            cls.tempdir.startswith('/tmp/leap_tests-'), -            "beware! tried to remove a dir which does not " -            "live in temporal folder!") -        shutil.rmtree(cls.tempdir) - -    # you have to override these methods -    # this way we ensure we did not put anything -    # here that you can forget to call. - -    def setUp(self): -        """not implemented""" -        raise NotImplementedError("abstract base class") - -    def tearDown(self): -        """not implemented""" -        raise NotImplementedError("abstract base class") - -    # -    # helper methods -    # - -    def _missing_test_for_plat(self, do_raise=False): -        """ -        Raises NotImplementedError for this platform -        if do_raise is True - -        @param do_raise: flag to actually raise exception -        @type do_raise: bool -        """ -        if do_raise: -            raise NotImplementedError( -                "This test is not implemented " -                "for the running platform: %s" % -                self._system) - -    def get_tempfile(self, filename): -        """ -        Returns the path of a given filename -        prepending the temporal dir associated with this -        TestCase - -        @param filename: the filename -        @type filename: str -        """ -        return os.path.join(self.tempdir, filename) - -    def touch(self, filepath): -        """ -        Touches a filepath, creating folders along -        the way if needed. - -        @param filepath: path to be touched -        @type filepath: str -        """ -        folder, filename = os.path.split(filepath) -        if not os.path.isdir(folder): -            mkdir_p(folder) -        self.assertTrue(os.path.isdir(folder)) -        with open(filepath, 'w') as fp: -            fp.write(' ') -        self.assertTrue(os.path.isfile(filepath)) - -    def chmod600(self, filepath): -        """ -        Chmods 600 a file - -        @param filepath: filepath to be chmodded -        @type filepath: str -        """ -        check_and_fix_urw_only(filepath) diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/https_server.py b/debian/python-leap.common/usr/share/pyshared/leap/common/testing/https_server.py deleted file mode 100644 index 08d5089..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/https_server.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- -# leap.common.testing.https_server.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. -""" -A simple HTTPS server to be used in tests -""" -from BaseHTTPServer import HTTPServer -import os -import ssl -import SocketServer -import threading -import unittest - -_where = os.path.split(__file__)[0] - - -def where(filename): -    return os.path.join(_where, filename) - - -class HTTPSServer(HTTPServer): -    def server_bind(self): -        SocketServer.TCPServer.server_bind(self) -        self.socket = ssl.wrap_socket( -            self.socket, server_side=True, -            certfile=where("leaptestscert.pem"), -            keyfile=where("leaptestskey.pem"), -            ca_certs=where("cacert.pem"), -            ssl_version=ssl.PROTOCOL_SSLv23) - - -class TestServerThread(threading.Thread): -    def __init__(self, test_object, request_handler): -        threading.Thread.__init__(self) -        self.request_handler = request_handler -        self.test_object = test_object - -    def run(self): -        self.server = HTTPSServer(('localhost', 0), self.request_handler) -        host, port = self.server.socket.getsockname() -        self.test_object.HOST, self.test_object.PORT = host, port -        self.test_object.server_started.set() -        self.test_object = None -        try: -            self.server.serve_forever(0.05) -        finally: -            self.server.server_close() - -    def stop(self): -        self.server.shutdown() - - -class BaseHTTPSServerTestCase(unittest.TestCase): -    """ -    derived classes need to implement a request_handler -    """ -    def setUp(self): -        self.server_started = threading.Event() -        self.thread = TestServerThread(self, self.request_handler) -        self.thread.start() -        self.server_started.wait() - -    def tearDown(self): -        self.thread.stop() - -    def get_server(self): -        host, port = self.HOST, self.PORT -        if host == "127.0.0.1": -            host = "localhost" -        return "%s:%s" % (host, port) - - -if __name__ == "__main__": -    unittest.main() diff --git a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/test_basetest.py b/debian/python-leap.common/usr/share/pyshared/leap/common/testing/test_basetest.py deleted file mode 100644 index 220e28d..0000000 --- a/debian/python-leap.common/usr/share/pyshared/leap/common/testing/test_basetest.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# test_basetest.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program.  If not, see <http://www.gnu.org/licenses/>. -""" -Unittests for BaseLeapTest ...becase it's oh so meta -""" -try: -    import unittest2 as unittest -except ImportError: -    import unittest - -import os -import StringIO - -from leap.common.testing.basetest import BaseLeapTest - -_tempdir = None  # global for tempdir checking - - -class _TestCaseRunner(object): -    """ -    TestCaseRunner used to run BaseLeapTest -    """ -    def run_testcase(self, testcase=None): -        """ -        Runs a given TestCase - -        @param testcase: the testcase -        @type testcase: unittest.TestCase -        """ -        if not testcase: -            return None -        loader = unittest.TestLoader() -        suite = loader.loadTestsFromTestCase(testcase) - -        # Create runner, and run testcase -        io = StringIO.StringIO() -        runner = unittest.TextTestRunner(stream=io) -        results = runner.run(suite) -        return results - - -class TestAbstractBaseLeapTest(unittest.TestCase, _TestCaseRunner): -    """ -    TestCase for BaseLeapTest abs -    """ -    def test_abstract_base_class(self): -        """ -        Test errors raised when setup/teardown not overloaded -        """ -        class _BaseTest(BaseLeapTest): -            def test_dummy_method(self): -                pass - -            def test_tautology(self): -                assert True - -        results = self.run_testcase(_BaseTest) - -        # should be 2 errors: NotImplemented -        # raised for setUp/tearDown -        self.assertEquals(results.testsRun, 2) -        self.assertEquals(len(results.failures), 0) -        self.assertEquals(len(results.errors), 2) - - -class TestInitBaseLeapTest(BaseLeapTest): -    """ -    TestCase for testing initialization of BaseLeapTest -    """ - -    def setUp(self): -        """nuke it""" -        pass - -    def tearDown(self): -        """nuke it""" -        pass - -    def test_path_is_changed(self): -        """tests whether we have changed the PATH env var""" -        os_path = os.environ['PATH'] -        self.assertTrue(os_path.startswith(self.tempdir)) - -    def test_old_path_is_saved(self): -        """tests whether we restore the PATH env var""" -        self.assertTrue(len(self.old_path) > 1) - - -class TestCleanedBaseLeapTest(unittest.TestCase, _TestCaseRunner): -    """ -    TestCase for testing tempdir creation and cleanup -    """ - -    def test_tempdir_is_cleaned_after_tests(self): -        """ -        test if a TestCase derived from BaseLeapTest creates and cleans the -        temporal dir -        """ -        class _BaseTest(BaseLeapTest): -            def setUp(self): -                """set global _tempdir to this instance tempdir""" -                global _tempdir -                _tempdir = self.tempdir - -            def tearDown(self): -                """nothing""" -                pass - -            def test_tempdir_created(self): -                """test if tempdir was created""" -                self.assertTrue(os.path.isdir(self.tempdir)) - -            def test_tempdir_created_on_setupclass(self): -                """test if tempdir is the one created by setupclass""" -                self.assertEqual(_tempdir, self.tempdir) - -        results = self.run_testcase(_BaseTest) -        self.assertEquals(results.testsRun, 2) -        self.assertEquals(len(results.failures), 0) -        self.assertEquals(len(results.errors), 0) - -        # did we cleaned the tempdir? -        self.assertFalse(os.path.isdir(_tempdir)) - -if __name__ == "__main__": -    unittest.main() diff --git a/debian/python-leap.common/usr/share/python/ns/python-leap.common b/debian/python-leap.common/usr/share/python/ns/python-leap.common deleted file mode 100644 index 2905ed7..0000000 --- a/debian/python-leap.common/usr/share/python/ns/python-leap.common +++ /dev/null @@ -1 +0,0 @@ -leap | 
