summaryrefslogtreecommitdiff
path: root/debian/python-leap.common/usr/share/pyshared
diff options
context:
space:
mode:
Diffstat (limited to 'debian/python-leap.common/usr/share/pyshared')
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap.common-0.2.3_dev-nspkg.pth1
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/__init__.py19
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/certs.py179
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/check.py61
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/config/__init__.py0
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/config/baseconfig.py185
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/config/pluggableconfig.py475
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/config/prefixers.py132
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/events/__init__.py100
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/events/component.py238
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/events/daemon.py208
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/events/events_pb2.py371
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/events/mac_auth.py31
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/events/server.py149
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/files.py126
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/__init__.py286
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/errors.py46
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/gpg.py397
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/keys.py230
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/keymanager/openpgp.py459
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/testing/__init__.py0
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/testing/basetest.py140
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/testing/https_server.py87
-rw-r--r--debian/python-leap.common/usr/share/pyshared/leap/common/testing/test_basetest.py140
24 files changed, 0 insertions, 4060 deletions
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()