← Back to team overview

launchpad-dev team mailing list archive

Re: Instead of authorizing individual applications against the Launchpad web service, let's authorize the Ubuntu desktop as a whole

 

After talks with the USSO desktop team, Kees Cook, Ubuntu developer
Didier Roche, and Kubuntu developer Johnathan Riddell, I'm back to
update this thread. I know a lot more about the GNOME keyring, I've
made some tweaks, and I think I can present my design in a more
convincing way.

Restatement of the status quo
=============================

On the server side, Launchpad credentials are associated with a
consumer key (the name of the application that requested the
credential). Each credential has an associated access level which
limits what the application can do under your name.

On the client side, launchpadlib's login_with() method caches
credentials unencrypted in your ~/.launchpadlib/[host]/credentials
directory. The get_token_and_login() method can be used to get a token
without writing it to /credentials, but most applications use
login_with(), and most of the ones I've seen use get_token_and_login()
also write the token to disk somewhere.

This setup works great when integrating other websites into Launchpad,
because you don't have any control over (eg.) Facebook, and because
third-party websites don't all share a data store. Although
third-party websites can use launchpadlib, they can't use
login_with(), which is designed for desktop use.

This setup doesn't make much sense when integrating desktop
applications running in a GNOME environment. You have control over the
environment. Any application running as you can easily access your
credentials and act as the union of all your OAuth tokens. Not only
that, login_with() stores the tokens unencrypted on disk. Unless
you've enabled home directory encryption, if your hard drive is
stolen, all of your credentials will be compromised.

Restatement of my design
========================

Now I'll restate my design as a two-step process. I hope I can make at
least the first step sound uncontroversial.

Step 1: Store credentials in the GNOME keyring
----------------------------------------------

The first improvement is to change login_with() to start storing
Launchpad credentials in the GNOME keyring (if available), with disk
storage as a fallback. This will prevent the stolen-hard-drive attack.

With Launchpad credentials in the GNOME keyring, a suitably paranoid
end-user can also take countermeasures against certain other attacks
by moving their Launchpad credentials out of the "login" keyring
(where they will be stored by default) and into a keyring for which
they've set an idle timeout. You can do this from the "Passwords and
Encryption Keys" desktop accessory.

Idle timeout sidebar
~~~~~~~~~~~~~~~~~~~

 Setting an idle timeout means that if you unlock a keyring and then
 walk away from your computer for N seconds, the keyring will
 automatically lock back up. The next time any application wants
 access to one of the keys in that keyring, you'll have to type your
 unlock phrase again.

 This stops an attack where someone stops by your running computer
 when you're not around, and snoops on your passwords. It also offers
 a little protection against malware that tries to dump an unlocked
 keyring: if you suddenly get a password dialogue out of nowhere,
 you'd do well to be suspicious. It doesn't protect against a
 keylogger.

 If you set the idle timeout to 0 seconds, you will have to type your
 unlock password *every* time an application wants access to *any* key
 in that keyring. If you're careful, this will give you complete
 protection against malware that tries to dump a keyring. It still
 won't protect against a keylogger, though.

Step 2: Authorize the desktop, not the application
--------------------------------------------------

Setting an idle timeout offers you some additional options for
security. But even if you set your idle timeout to zero, you have no
way of ensuring that the 'apport' credential is only used by the
apport application.[Footnote 1] Any authorized application can access
your entire keyring.

The second improvement is to acknowledge this, by relaxing the
requirement that each desktop app have its own individually authorized
OAuth token, while maintaining that requirement for integrated
websites. This should have the side effect of solving the problem I'm
actually trying to solve--getting third-party developers to accept the
token authorization process instead of trying to hack around it.

The desktop authorization will be done through a one-time browser
open, as described in my earlier email. Desktop authorization can be
done permanently or on a time-limited basis, and revoked at any time
from the Launchpad website. Token expiration or revocation will cause
another browser open.

(About) as good as it gets
==========================

Why am I basing this design around a system (the GNOME keyring) that
has obvious shortcomings? Because what we're doing now is worse, and
because there's nothing lying around that's better than the GNOME
keyring.

It's not hard to come up with a better system than the one I
propose. But my proposal has five desirable properties:

 a) Brings our security *up* to the standards set by GNOME and the
 Ubuntu Single Sign-On project.

 b) Doesn't assume desktop improvements that might or might not ever
 happen (see below).

 c) Addresses the problem I'm really trying to solve: that third-party
 developers find our *existing* per-app authorization system too
 onerous.

 d) Doesn't require any desktop development up front, although desktop
 developers can improve its usability later (see below).

 e) Can be deprecated in favor of a real per-app authorization system
 if the desktop improvements ever happen--assuming we can come up with
 a design that third-party developers will put up with.

Most of the alternate designs I've seen/invented come up short in b or
c, which are deal-breakers IMO; as well as in d, which is not. I can
argue specific cases off-list if anyone is interested.

When will the GNOME keyring improve?
====================================

We'd look pretty silly if we went to desktop-wide integration and then
the next release of GNOME featured per-application per-key ACLs. It
would still be a lot of work to _implement_ a per-application
authorization system that wouldn't drive our third-party developers to
cheap hacks, but it would be theoretically possible.

But, it doesn't look likely to happen anytime soon. This is from
http://live.gnome.org/GnomeKeyring/SecurityPhilosophy:

---
 While it'd be nice for gnome-keyring to someday be hardened against
 active attacks originating from the user's session, the reality is
 that the free software "desktop" today just isn't architected with
 those things in mind. We need completion and integration things like
 the following. Kudos to the great folks working on parts of this
 stuff:

     * Trusted X (for prompting)
     * Pervasive use of security contexts for different apps (SELinux,
AppArmor)
     * Application signing (for ACLs)
 ---

Those are some heavy prerequisites.

According to Didier Roche, GNOME 2.28 included a very simple step
towards protecting against active attacks: a dialog that pops up the
first time some application wants access to a keyring, letting you
grant or deny access.

That's not exactly the feature we want, but it's a start. In order to
limit access by application, we need to correctly identify which
application wants access. But we won't even get this feature. The
feature was *removed* after it became clear that, without application
signing, it's trivial to spoof the name of an already-allowed
application.

At the most recent GUADEC, Didier and some other developers discussed
alternate ways of doing this feature, but didn't come up with anything
good.

I took a look at the KDE Wallet, the closest competitor to the GNOME
keyring, to see if there's something the GNOME developers were
missing. The stories are pretty much the same. Once an application has
access to your wallet, it has access to that _entire_
wallet. ("Wallet" here means "keyring"--you can have more than one.)

You can ban bad applications from your wallets, and you can put a
watch on your wallets so that you get notified any time a new
application tries to get access. But there's no verification that an
application is what it claims to be. According to Jonathan Riddell,
"the application name is taken from the KAboutData", which is easy to
spoof. This feature is basically the one added to GNOME and then
removed.

Desktop-based improvements we could do now
==========================================

Benji and I plan to do the work necessary to implement steps 1 and 2
of this design. There are some additional improvements possible on top
of that, to improve the experience on the desktop. Any of these may
require additional server-side design and implementation work, which
I'm happy to do, given a partner who's serious about the desktop side.

3. Martin's suggestion. If a user's Launchpad account is tied into
their USSO account, it's theoretically possible to exchange USSO
credentials for Launchpad credentials without opening a web
browser. Since all users now (and most users in the future) tie their
Launchpad account into their USSO account, this would be a big
usability win, getting rid of browser opens entirely for many users.

4. Kees is interested in seeing a new gnome-keyring backend for
managing Launchpad tokens. IMO this backend can't do all that much,
given that it's still using gnome-keyring. But it could provide some
benefits, like the ability to limit the client-side storage of a token
to the current session.

Conclusion
==========

There are a lot of good ideas in this thread, but many of them require
that the GNOME keyring know which application is asking for a key,
the way Launchpad knows which user is making a request. Unfortunately, 
it doesn't know, and it won't know for the forseeable future.

Without this ability, there's not much point in keeping more than one
set of Launchpad credentials on the desktop. The best thing to do from
a user-experience standpoint is to authorize the desktop itself, rather
than individual applications.

Footnote 1
==========
(from "Step 2: Authorize the desktop, not the application")

You can approximate this behavior by creating more keyrings. For
instance, you create a separate zero-timeout keyring for each
Launchpad access level: "read public", "read private", etc. Keep your
Launchpad credentials sorted by access level. Give each keyring a
different password. Be sure to only unlock the appropriate keyring for
the application you're running.

This won't stop one app from using another app's credentials, but it
will stop one app from claiming a higher access level than you gave
it.

If you absolutely want to prevent one app from using another app's
credentials, you can create a separate keyring for each application,
each keyring named after the application.

These schemes are far too tedious and complicated for anyone to put up
with, and they won't stop a simple userspace keylogger. They also
won't stop malware from waiting around and making fake requests for
the tokens of the applications you're running, or opening fake windows
that ask for the unlock key.

Leonard

Attachment: signature.asc
Description: This is a digitally signed message part


Follow ups

References