diff options
| -rw-r--r-- | changes/feature_4284-download-smtp-certs | 1 | ||||
| -rw-r--r-- | src/leap/bitmask/crypto/certs.py | 38 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/smtpbootstrapper.py | 6 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/smtpconfig.py | 7 | 
4 files changed, 35 insertions, 17 deletions
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),  | 
