emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH RFC] GnuTLS: Support TOFU certificate checking.


From: Ted Zlatanov
Subject: Re: [PATCH RFC] GnuTLS: Support TOFU certificate checking.
Date: Wed, 08 Oct 2014 10:52:33 -0400
User-agent: Gnus/5.130012 (Ma Gnus v0.12) Emacs/24.4.50 (darwin)

On Tue,  7 Oct 2014 23:16:05 +0200 Toke Høiland-Jørgensen <address@hidden> 
wrote: 

TH> This implements rudimentary Trust On First Use certificate checking in
TH> gnutls.c. This is useful for protecting against MITM attacks when
TH> connecting to servers using self-signed certificates, as well as to
TH> guard against rogue or compromised CAs issuing illegitimate
TH> certificates that would otherwise be accepted.

Wonderful work, thank you!

You should check in the autoconf script whether
`gnutls_verify_stored_pubkey' is available.  It's a fairly new function
and we have to support older versions of GnuTLS without it.

TH> (require 'gnutls)
TH> (setq gnutls-verify-error '((".*" :tofu))
TH> (open-gnutls-stream "test" nil "google.com" 443) ; this should fail

TH> To add the certificate to the trust store, execute (in a shell)
TH> `gnutls-cli --tofu -p 443 google.com` and answer yes when it asks
TH> whether to trust the certificate. Doing so should cause the open to
TH> success the next time around.

I like the simplicity of it. It would be nice to do this inside Emacs
itself (it's OK if it requires some kind of `emacs --batch' call,
doesn't have to be immediate). Either way, the errors should tell us
specifically what to run from the command line in these two cases:

    error ("No TOFU trust entry found for hostname \"%s\" and service \"%s\"", 
c_hostname, c_service);
    error ("TOFU trust MISMATCH for hostname \"%s\" and service \"%s\"", 
c_hostname, c_service);

TH> 1. Would this be viable to include at all? And if so, is this the right
TH>    way to go about it?

I think it's good enough to include right now.  We can iterate the
design from the C side but the Lisp side seems simple enough.  I would
even make :tofu the default (we've had debates on whether it should be t
but IMHO :tofu is a better default).

TH> 2. There's currently no way to add a certificate to the store when it's
TH>    first seen. What's the best way to go about this? I'm not sure how to
TH>    actually communicate with the user from within gnutls-boot.

You can't, that's been the problem so far. That's a very picky part of
the Emacs code and breaking out for any kind of interaction caused
problems. That's why I like your pragmatic solution above.  But Lars'
proposal may be the nicer way if it can be hacked into place.

TH> 3. Currently this uses the global (well, per-user) GnuTLS certificate
TH>    store. My thought was this makes the most sense (it's still per-port,
TH>    so the same hostname can have different certificates for different
TH>    services). But is it?

I think so. But Emacs creates a Emacs-specific homedir for the GnuPG
keychain, for verification of the package archives, in
`~/.emacs.d/gnupg' which is an equally valid approach. So I don't have a
strong opinion.

What's the drawback of having a dedicated Emacs store? Do any other
programs besides `gnutls-cli` use the global GnuTLS store?

The planned certificate management UI can hide these choices from the
user and make the add/remove/list pinned cert operations simple.

TH> 4. Setting gnutls-verify-error to t does not activate TOFU checking. The
TH>    reasoning behind this is that TOFU works somewhat differently than
TH>    the other trust models (CA and hostname matching), and so is a
TH>    feature that is probably best left for people to explicitly ask for.
TH>    Is this reasonable?

I'm OK with that.

TH> 5. Any other comments. For instance, I have only tested this on Linux,
TH>    so not sure if I fudged up all the library loading magic for W32...

Don't worry about it much, it's fixable (modulo the autoconf note above).

TH> As an aside, while testing this I found that using customize to set
TH> gnutls-verify-error, a doubly-nested list of symbols would end up
TH> getting passed to gnutls-boot, which would then subsequently fail all
TH> the membership tests on it. This seems to stem from the fact that
TH> customize produces list entries of the form '((".*" (:tofu))) while
TH> gnutls-negotiate passes the cdr of each matched entry to cl-mapcan. Not
TH> sure which should be fixed, so I just set it manually while testing, but
TH> thought I'd point it out :)

If you can submit a bug with this, it would be wonderful.  I've been
meaning to get rid of the `cl-mapcan' call anyhow.

On Wed, 08 Oct 2014 14:18:27 +0200 Lars Magne Ingebrigtsen <address@hidden> 
wrote: 

LMI> I think it would also be nice if the entire cert was also returned (in a
LMI> convenient format), so that Emacs can display the pertinent parts while
LMI> querying the user about what action to take.

LMI> Like "signed by CA foo on date baz for host zot" and so on.

I am personally not too concerned about putting that at the ELisp level,
but it certainly changes the GnuTLS code fundamentally.  Right now it
stays at the C level to do everything, which is a bit more secure and
more standard.

On Wed, 08 Oct 2014 15:06:52 +0200 Lars Magne Ingebrigtsen <address@hidden> 
wrote: 

LMI> Eli Zaretskii <address@hidden> writes:

>> How can it return a valid descriptor without all the validations it
>> does before that, which (AFAIU) you want to delegate to Lisp now?

LMI> It would validate the certificate, but never drop the connection even if
LMI> the certificate is invalid.  It would be up to `open-network-stream' to
LMI> close the connection if the user decides to not accept the invalid (or
LMI> self-signed) certificate.

I think that's pretty tricky with GnuTLS because it expects all the
validations to be C callbacks and just hands off the connection at the
end. You're not supposed to interact with the session during the
validation, IIUC. So it will probably require two attempts.

Do you want to ask in the GnuTLS mailing list?  Or I can?

On Wed, 08 Oct 2014 15:28:23 +0200 Toke Høiland-Jørgensen <address@hidden> 
wrote: 

TH> Another alternative would be to fail in the C code and report why, along
TH> with the cert details; and then make it up to the lisp code to retry the
TH> connection with appropriate flags set to ignore (some) errors based on
TH> user response... That would be similar to how the gnutls lisp/C
TH> interaction is now (I think), with the addition that certificate details
TH> are returned along with any errors signalled...

Yes, that would be nice and clean. They can simply be attached as symbol
properties to the error.  Maybe you can adjust `gnutls_make_error'?

On Wed, 08 Oct 2014 15:25:43 +0200 Lars Magne Ingebrigtsen <address@hidden> 
wrote: 

LMI> The other option is to have the C layer close the connection, signal an
LMI> error, have `open-network-stream' query the user about the invalid
LMI> certificate, the user says "connect anyway", and then we'd reconnect
LMI> with other options.

LMI> That seems less ... convenient.

Unfortunately, I think it's how you're supposed to use GnuTLS.  But I'm
happy to be proven wrong!

On Wed, 08 Oct 2014 13:58:50 +0200 Lars Magne Ingebrigtsen <address@hidden> 
wrote: 

LMI> Lars Magne Ingebrigtsen <address@hidden> writes:

>> Yes, `open-network-stream' would implement certificate pinning. 

LMI> (By default.  But there should probably be a way for the user to switch
LMI> it off, since the user may not want to store a list of servers (with
LMI> self-signed certificates) it has talked to -- for privacy reasons.  But
LMI> that's a pretty marginal issue.)

Yeah, I think it can be implemented later.

Ted




reply via email to

[Prev in Thread] Current Thread [Next in Thread]