summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/bonafide
diff options
context:
space:
mode:
authorRuben Pollan <meskio@sindominio.net>2016-09-06 19:27:31 +0200
committerKali Kaneko (leap communications) <kali@leap.se>2016-09-07 10:04:45 -0400
commit7a6e187e0a970ad6fb722fc9dfd3be784b254c06 (patch)
tree70092fe6f1635b7a22266c8e136510eb6934f162 /src/leap/bitmask/bonafide
parent1d51bc24ec9afcbb30b05905217bc7aafedca5f1 (diff)
[feat] Add manual provider registration
- Resolves: #8400
Diffstat (limited to 'src/leap/bitmask/bonafide')
-rw-r--r--src/leap/bitmask/bonafide/_protocol.py22
-rw-r--r--src/leap/bitmask/bonafide/config.py54
-rw-r--r--src/leap/bitmask/bonafide/errors.py23
-rw-r--r--src/leap/bitmask/bonafide/service.py23
4 files changed, 102 insertions, 20 deletions
diff --git a/src/leap/bitmask/bonafide/_protocol.py b/src/leap/bitmask/bonafide/_protocol.py
index 3986540..ff357a1 100644
--- a/src/leap/bitmask/bonafide/_protocol.py
+++ b/src/leap/bitmask/bonafide/_protocol.py
@@ -21,10 +21,10 @@ import os
import resource
from collections import defaultdict
-from leap.common.config import get_path_prefix
from leap.bitmask.bonafide import config
from leap.bitmask.bonafide.provider import Api
from leap.bitmask.bonafide.session import Session, OK
+from leap.common.config import get_path_prefix
from twisted.cred.credentials import UsernamePassword
from twisted.internet.defer import fail
@@ -77,11 +77,11 @@ class BonafideProtocol(object):
# Service public methods
- def do_signup(self, full_id, password):
+ def do_signup(self, full_id, password, autoconf=False):
log.msg('SIGNUP for %s' % full_id)
_, provider_id = config.get_username_and_provider(full_id)
- provider = config.Provider(provider_id)
+ provider = config.Provider(provider_id, autoconf=autoconf)
d = provider.callWhenReady(
self._do_signup, provider, full_id, password)
return d
@@ -102,10 +102,10 @@ class BonafideProtocol(object):
d.addErrback(self._del_session_errback, full_id)
return d
- def do_authenticate(self, full_id, password):
+ def do_authenticate(self, full_id, password, autoconf=False):
_, provider_id = config.get_username_and_provider(full_id)
- provider = config.Provider(provider_id)
+ provider = config.Provider(provider_id, autoconf=autoconf)
def maybe_finish_provider_bootstrap(result, provider):
session = self._get_session(provider, full_id, password)
@@ -147,6 +147,18 @@ class BonafideProtocol(object):
d.addCallback(lambda _: '%s logged out' % full_id)
return d
+ def do_get_provider(self, provider_id, autoconf=False):
+ provider = config.Provider(provider_id, autoconf=autoconf)
+ return provider.callWhenMainConfigReady(provider.config)
+
+ def do_provider_delete(self, provider_id):
+ return config.delete_provider(provider_id)
+
+ def do_provider_list(self, seeded=False):
+ # TODO: seeded, we don't have pinned providers yet
+ providers = config.list_providers()
+ return [{"domain": p} for p in providers]
+
def do_get_smtp_cert(self, full_id):
if (full_id not in self._sessions or
not self._sessions[full_id].is_authenticated):
diff --git a/src/leap/bitmask/bonafide/config.py b/src/leap/bitmask/bonafide/config.py
index 0288676..8ef6c1b 100644
--- a/src/leap/bitmask/bonafide/config.py
+++ b/src/leap/bitmask/bonafide/config.py
@@ -20,6 +20,7 @@ Configuration for a LEAP provider.
import datetime
import json
import os
+import shutil
import sys
from collections import defaultdict
@@ -30,12 +31,14 @@ from twisted.internet.ssl import ClientContextFactory
from twisted.python import log
from twisted.web.client import Agent, downloadPage
+from leap.bitmask.bonafide._http import httpRequest
+from leap.bitmask.bonafide.provider import Discovery
+from leap.bitmask.bonafide.errors import NotConfiguredError
+
from leap.common.check import leap_assert
from leap.common.config import get_path_prefix as common_get_path_prefix
from leap.common.files import mkdir_p
# check_and_fix_urw_only, get_mtime
-from leap.bitmask.bonafide._http import httpRequest
-from leap.bitmask.bonafide.provider import Discovery
APPNAME = "bonafide"
@@ -126,6 +129,27 @@ def get_username_and_provider(full_id):
return full_id.split('@')
+def list_providers():
+ path = os.path.join(_preffix, "leap", "providers")
+ path = os.path.expanduser(path)
+ return os.listdir(path)
+
+
+def delete_provider(domain):
+ path = os.path.join(_preffix, "leap", "providers", domain)
+ path = os.path.expanduser(path)
+ if not os.path.exists(path):
+ raise NotConfiguredError("Provider %s is not configured, can't be "
+ "deleted" % (domain,))
+ shutil.rmtree(path)
+
+ # FIXME: this feels hacky, can we find a better way??
+ if domain in Provider.first_bootstrap:
+ del Provider.first_bootstrap[domain]
+ if domain in Provider.ongoing_bootstrap:
+ del Provider.ongoing_bootstrap[domain]
+
+
class Provider(object):
# TODO add validation
@@ -137,8 +161,9 @@ class Provider(object):
ongoing_bootstrap = defaultdict(None)
stuck_bootstrap = defaultdict(None)
- def __init__(self, domain, autoconf=True, basedir=None,
+ def __init__(self, domain, autoconf=False, basedir=None,
check_certificate=True):
+ # TODO: I need a way to know if it was already configured
if not basedir:
basedir = os.path.join(_preffix, 'leap')
self._basedir = os.path.expanduser(basedir)
@@ -162,10 +187,14 @@ class Provider(object):
self._load_provider_json()
- if not is_configured and autoconf:
- log.msg('provider %s not configured: downloading files...' %
- domain)
- self.bootstrap()
+ if not is_configured:
+ if autoconf:
+ log.msg('provider %s not configured: downloading files...' %
+ domain)
+ self.bootstrap()
+ else:
+ raise NotConfiguredError("Provider %s is not configured"
+ % (domain,))
else:
log.msg('Provider already initialized')
self.first_bootstrap[self._domain] = defer.succeed(
@@ -191,15 +220,17 @@ class Provider(object):
def is_configured(self):
provider_json = self._get_provider_json_path()
- # XXX check if all the services are there
if not is_file(provider_json):
return False
if not is_file(self._get_ca_cert_path()):
return False
- if not self.has_config_for_all_services():
- return False
return True
+ def config(self):
+ if not self._provider_config:
+ self._load_provider_json()
+ return self._provider_config.dict()
+
def bootstrap(self):
domain = self._domain
log.msg("Bootstrapping provider %s" % domain)
@@ -491,6 +522,9 @@ class Record(object):
def __init__(self, **kw):
self.__dict__.update(kw)
+ def dict(self):
+ return self.__dict__
+
class WebClientContextFactory(ClientContextFactory):
def getContext(self, hostname, port):
diff --git a/src/leap/bitmask/bonafide/errors.py b/src/leap/bitmask/bonafide/errors.py
new file mode 100644
index 0000000..485c43e
--- /dev/null
+++ b/src/leap/bitmask/bonafide/errors.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+# errors.py
+# Copyright (C) 2016 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/>.
+"""
+Exceptions for bonafide
+"""
+
+
+class NotConfiguredError(Exception):
+ pass
diff --git a/src/leap/bitmask/bonafide/service.py b/src/leap/bitmask/bonafide/service.py
index deead22..5e3b0f1 100644
--- a/src/leap/bitmask/bonafide/service.py
+++ b/src/leap/bitmask/bonafide/service.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# service.py
-# Copyright (C) 2015-2016 LEAP
+# Copyright (C) 2015 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
@@ -14,6 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
"""
Bonafide Service.
"""
@@ -50,7 +51,7 @@ class BonafideService(HookableService):
# Commands
- def do_authenticate(self, username, password):
+ def do_authenticate(self, username, password, autoconf=False):
def notify_passphrase_entry(username, password):
data = dict(username=username, password=password)
@@ -78,14 +79,14 @@ class BonafideService(HookableService):
notify_passphrase_entry(username, password)
- d = self._bonafide.do_authenticate(username, password)
+ d = self._bonafide.do_authenticate(username, password, autoconf)
d.addCallback(notify_bonafide_auth)
d.addCallback(lambda response: {
'srp_token': response[0], 'uuid': response[1]})
return d
- def do_signup(self, username, password):
- d = self._bonafide.do_signup(username, password)
+ def do_signup(self, username, password, autoconf=False):
+ d = self._bonafide.do_signup(username, password, autoconf)
d.addCallback(lambda response: {'signup': 'ok', 'user': response})
return d
@@ -102,6 +103,18 @@ class BonafideService(HookableService):
d.addCallback(lambda response: {'logout': 'ok'})
return d
+ def do_provider_create(self, domain):
+ return self._bonafide.do_get_provider(domain, autoconf=True)
+
+ def do_provider_read(self, domain):
+ return self._bonafide.do_get_provider(domain)
+
+ def do_provider_delete(self, domain):
+ return self._bonafide.do_provider_delete(domain)
+
+ def do_provider_list(self, seeded=False):
+ return self._bonafide.do_provider_list(seeded)
+
def do_get_smtp_cert(self, username=None):
if not username:
username = self._active_user