From ce63b5a0277b3ff062d04a17af9e9a927b7d9b87 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 2 Sep 2015 16:04:06 -0400 Subject: [feature] retrieve specific smtp certificate. Closes: #4284 --- changes/feature_4284-download-smtp-certs | 1 + src/leap/bitmask/crypto/certs.py | 38 ++++++++++++++-------- src/leap/bitmask/services/mail/smtpbootstrapper.py | 6 ++-- src/leap/bitmask/services/mail/smtpconfig.py | 7 +++- 4 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 changes/feature_4284-download-smtp-certs diff --git a/changes/feature_4284-download-smtp-certs b/changes/feature_4284-download-smtp-certs new file mode 100644 index 00000000..929bd858 --- /dev/null +++ b/changes/feature_4284-download-smtp-certs @@ -0,0 +1 @@ +- Download specific smtp certificate from provider, instead of using the vpn one. Closes: #4284 diff --git a/src/leap/bitmask/crypto/certs.py b/src/leap/bitmask/crypto/certs.py index 4b669376..017af144 100644 --- a/src/leap/bitmask/crypto/certs.py +++ b/src/leap/bitmask/crypto/certs.py @@ -30,7 +30,7 @@ from leap.common import certs as leap_certs logger = get_logger() -def download_client_cert(provider_config, path, session): +def download_client_cert(provider_config, path, session, kind="vpn"): """ Downloads the client certificate for each service. @@ -41,32 +41,45 @@ def download_client_cert(provider_config, path, session): :param session: a fetcher.session instance. For the moment we only support requests.sessions :type session: requests.sessions.Session + :param kind: the kind of certificate being requested. Valid values are + "vpn" or "smtp". + :type kind: string """ - # TODO we should implement the @with_srp_auth decorator - # again. srp_auth = SRPAuth(provider_config) session_id = srp_auth.get_session_id() token = srp_auth.get_token() cookies = None if session_id is not None: cookies = {"_session_id": session_id} - cert_uri = "%s/%s/cert" % ( + + if kind == "vpn": + cert_uri_template = "%s/%s/cert" + method = 'get' + params = {} + elif kind == 'smtp': + cert_uri_template = "%s/%s/smtp_cert" + method = 'post' + params = {'address': srp_auth.get_username()} + else: + raise ValueError("Incorrect value passed to kind parameter") + + cert_uri = cert_uri_template % ( provider_config.get_api_uri(), provider_config.get_api_version()) - logger.debug('getting cert from uri: %s' % cert_uri) + + logger.debug('getting %s cert from uri: %s' % (kind, cert_uri)) headers = {} # API v2 will only support token auth, but in v1 we can send both if token is not None: - headers["Authorization"] = 'Token token="{0}"'.format(token) + headers["Authorization"] = 'Token token={0}'.format(token) - res = session.get(cert_uri, - verify=provider_config - .get_ca_cert_path(), - cookies=cookies, - timeout=REQUEST_TIMEOUT, - headers=headers) + call = getattr(session, method) + res = call(cert_uri, verify=provider_config.get_ca_cert_path(), + cookies=cookies, params=params, + timeout=REQUEST_TIMEOUT, + headers=headers, data=params) res.raise_for_status() client_cert = res.content @@ -74,7 +87,6 @@ def download_client_cert(provider_config, path, session): # XXX raise more specific exception. raise Exception("The downloaded certificate is not a " "valid PEM file") - mkdir_p(os.path.dirname(path)) try: diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index cd871803..a1b520ef 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -87,7 +87,7 @@ class SMTPBootstrapper(AbstractBootstrapper): logger.debug("Using hostname %s for SMTP" % (hostname,)) client_cert_path = self._smtp_config.get_client_cert_path( - self._provider_config, about_to_download=True) + self._userid, self._provider_config, about_to_download=True) if not is_file(client_cert_path): # For re-download if something is wrong with the cert @@ -101,7 +101,7 @@ class SMTPBootstrapper(AbstractBootstrapper): download_client_cert(self._provider_config, client_cert_path, - self._session) + self._session, kind="smtp") def _start_smtp_service(self): """ @@ -117,7 +117,7 @@ class SMTPBootstrapper(AbstractBootstrapper): host = hosts[hostname][self.IP_KEY].encode("utf-8") port = hosts[hostname][self.PORT_KEY] client_cert_path = self._smtp_config.get_client_cert_path( - self._provider_config, about_to_download=True) + self._userid, self._provider_config, about_to_download=True) from leap.mail.smtp import setup_smtp_gateway diff --git a/src/leap/bitmask/services/mail/smtpconfig.py b/src/leap/bitmask/services/mail/smtpconfig.py index 2d8de411..f78b3449 100644 --- a/src/leap/bitmask/services/mail/smtpconfig.py +++ b/src/leap/bitmask/services/mail/smtpconfig.py @@ -53,19 +53,24 @@ class SMTPConfig(ServiceConfig): return self._safe_get_value("locations") def get_client_cert_path(self, + userid, providerconfig=None, about_to_download=False): """ Returns the path to the certificate used by smtp + :param userid: the user id, in user@provider form """ + leap_assert(userid, "Need an userid") leap_assert(providerconfig, "We need a provider") leap_assert_type(providerconfig, ProviderConfig) + username = userid.split("@")[0] + cert_path = os.path.join(get_path_prefix(), "leap", "providers", providerconfig.get_domain(), - "keys", "client", "smtp.pem") + "keys", "client", "smtp_%s.pem" % username) if not about_to_download: leap_assert(os.path.exists(cert_path), -- cgit v1.2.3