From 73a310ce49c91f0884d05a8d2cd8c96c3c5447d3 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 20 May 2017 17:09:28 -0400 Subject: developer keyring verification * gpg keyrings in /usr/share/debug-me/ will be checked to see if a connecting person is a known developer of software installed on the system, and so implicitly trusted already. Software packages/projects can install keyrings to that location. (Thanks to Sean Whitton for the idea.) * make install will install /usr/share/debug-me/debug-me_developer.gpg, which contains the key of Joey Hess. (stack and cabal installs don't include this file because they typically don't install system-wide) * debug-me.cabal: Added dependency on time. This commit was sponsored by Francois Marier on Patreon. --- CHANGELOG | 9 +++ ControlWindow.hs | 3 + Gpg/Keyring.hs | 73 +++++++++++++++++++++ Gpg/Wot.hs | 5 +- Makefile | 3 + debug-me.1 | 13 +++- debug-me.cabal | 13 +++- developer-keyring.gpg | Bin 0 -> 5646 bytes doc/faq.mdwn | 40 ++++++++--- doc/index.mdwn | 10 +-- doc/todo/use_distribution_keyrings.mdwn | 3 + ...ent_2_43e012511d2fc39d78789541482928b7._comment | 9 +++ 12 files changed, 160 insertions(+), 21 deletions(-) create mode 100644 Gpg/Keyring.hs create mode 100644 developer-keyring.gpg create mode 100644 doc/todo/use_distribution_keyrings/comment_2_43e012511d2fc39d78789541482928b7._comment diff --git a/CHANGELOG b/CHANGELOG index bafd9e9..e8ea5c1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,15 @@ debug-me (1.20170510) UNRELEASED; urgency=medium * debug-me is available in Debian unstable. + * gpg keyrings in /usr/share/debug-me/ will be checked + to see if a connecting person is a known developer of software + installed on the system, and so implicitly trusted already. + Software packages/projects can install keyrings to that location. + (Thanks to Sean Whitton for the idea.) + * make install installs /usr/share/debug-me/a_debug-me_developer.gpg, + which contains the key of Joey Hess. (stack and cabal installs don't + include this file because they typically don't install system-wide) + * debug-me.cabal: Added dependency on time. * stack.yaml: Update to new posix-pty version. -- Joey Hess Sat, 20 May 2017 13:47:27 -0400 diff --git a/ControlWindow.hs b/ControlWindow.hs index c5a6be9..bd79d0f 100644 --- a/ControlWindow.hs +++ b/ControlWindow.hs @@ -15,6 +15,7 @@ import ControlSocket import VirtualTerminal import Gpg import Gpg.Wot +import Gpg.Keyring import Output import System.IO @@ -163,6 +164,8 @@ askToAllow ochan promptchan responsechan k@(GpgSigned pk _ _) = do ws <- downloadWotStats gpgkeyid putStrLn $ unlines $ map sanitizeForDisplay $ describeWot ws ss + mapM_ (putStrLn . keyringToDeveloperDesc ws) + =<< findKeyringsContaining gpgkeyid promptconnect where promptconnect :: IO () diff --git a/Gpg/Keyring.hs b/Gpg/Keyring.hs new file mode 100644 index 0000000..a0fa242 --- /dev/null +++ b/Gpg/Keyring.hs @@ -0,0 +1,73 @@ +{- Copyright 2017 Joey Hess + - + - Licensed under the GNU AGPL version 3 or higher. + -} + +-- | Gpg keyrings for debug-me + +module Gpg.Keyring where + +import Gpg +import qualified Gpg.Wot + +import System.FilePath +import Data.Char +import System.Directory +import Data.Time.Clock +import Data.Time.Format +import System.Process +import System.Exit + +keyringDir :: FilePath +keyringDir = "/usr/share/debug-me/keyring" + +data Keyring = Keyring FilePath UTCTime + +keyringToDeveloperDesc :: Maybe (Gpg.Wot.WotStats) -> Keyring -> String +keyringToDeveloperDesc mws (Keyring f mtime) = + name ++ " is " ++ desc ++ " \t(as of " ++ showtime mtime ++ ")" + where + name = maybe "This person" Gpg.Wot.wotStatName mws + desc = map sanitize $ dropExtension $ takeFileName f + sanitize '_' = ' ' + sanitize c + | isAlphaNum c || c `elem` "-+" = c + | otherwise = '?' + showtime = formatTime defaultTimeLocale "%c" + +findKeyringsContaining :: GpgKeyId -> IO [Keyring] +findKeyringsContaining k = + go [] . map (keyringDir ) =<< getDirectoryContents keyringDir + where + go c [] = return c + go c (f:fs) = do + isfile <- doesFileExist f + if isfile && takeExtension f == ".gpg" + then do + inkeyring <- isInKeyring k f + if inkeyring + then do + mtime <- getModificationTime f + let keyring = Keyring f mtime + go (keyring : c) fs + else go c fs + else go c fs + +-- | Check if the gpg key is included in the keyring file. +-- +-- Similar to gpgv, this does not check if the key is revoked or expired, +-- only if it's included in the keyring. +isInKeyring :: GpgKeyId -> FilePath -> IO Bool +isInKeyring (GpgKeyId k) f = do + -- gpg assumes non-absolute keyring files are relative to ~/.gnupg/ + absf <- makeAbsolute f + let p = proc "gpg" + -- Avoid reading any keyrings except the specified one. + [ "--no-options" + , "--no-default-keyring" + , "--no-auto-check-trustdb" + , "--keyring", absf + , "--list-key", k + ] + (exitcode, _, _) <- readCreateProcessWithExitCode p "" + return (exitcode == ExitSuccess) diff --git a/Gpg/Wot.hs b/Gpg/Wot.hs index b29ccc7..2a6d541 100644 --- a/Gpg/Wot.hs +++ b/Gpg/Wot.hs @@ -107,7 +107,7 @@ describeWot (Just ws) (StrongSetAnalysis ss) , theirname ++ " is probably a real person." ] where - theirname = stripEmail (uid (key ws)) + theirname = wotStatName ws sigs = cross_sigs ws ++ other_sigs ws bestconnectedsigs = sortOn rank sigs describeWot Nothing _ = @@ -115,5 +115,8 @@ describeWot Nothing _ = , "Their identity cannot be verified!" ] +wotStatName :: WotStats -> String +wotStatName ws = stripEmail (uid (key ws)) + stripEmail :: String -> String stripEmail = unwords . takeWhile (not . ("<" `isPrefixOf`)) . words diff --git a/Makefile b/Makefile index 3244942..01eaad3 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,9 @@ install-files: debug-me install-mans install -m 0755 debug-me.init $(DESTDIR)$(PREFIX)/etc/init.d/debug-me install -d $(DESTDIR)$(PREFIX)/etc/default install -m 0644 debug-me.default $(DESTDIR)$(PREFIX)/etc/default/debug-me + install -d $(DESTDIR)$(PREFIX)/usr/share/debug-me/keyring + install -m 0655 developer-keyring.gpg \ + $(DESTDIR)$(PREFIX)/usr/share/debug-me/keyring/a_debug-me_developer.gpg install-mans: install -d $(DESTDIR)$(PREFIX)/usr/share/man/man1 diff --git a/debug-me.1 b/debug-me.1 index a0e108a..251e636 100644 --- a/debug-me.1 +++ b/debug-me.1 @@ -14,13 +14,16 @@ problem. Making your problem their problem gets it fixed fast. A debug-me session is logged and signed with the developer's GnuPG key, producing a chain of evidence of what they saw and what they did. So the developer's good reputation is leveraged to make debug-me secure. +If you trust a developer to ship software to your computer, +you can trust them to debug-me. .PP When you start debug-me without any options, it will connect to a debug-me server, and print out an url that you can give to the developer to get them connected to you. Then debug-me will show you their GnuPG key and who -has signed it. If the developer has a good reputation, you can proceed -to let them type into your console in a debug-me session. Once the -session is done, the debug-me server will email you the signed +has signed it, and will let you know if they are a known developer +of software on your computer. If the developer has a good reputation, you +can proceed to let them type into your console in a debug-me session. Once +the session is done, the debug-me server will email you the signed evidence of what the developer did in the session. .PP It's a good idea to watch the debug-me session. The developer should be @@ -101,6 +104,10 @@ exits. .IP "~/.debug-me/log/remote/" When using debug-me to connect to a remote session, the session will be logged to here. +.UP "/usr/share/debug-me/keyring/*.gpg" +When verifying a developer's gpg key, debug-me checks if it's listed in +the keyrings in this directory, which can be provided by software installed +on the computer. .SH SEE ALSO .PP diff --git a/debug-me.cabal b/debug-me.cabal index 10b184e..3750f00 100644 --- a/debug-me.cabal +++ b/debug-me.cabal @@ -20,13 +20,16 @@ Description: A debug-me session is logged and signed with the developer's GnuPG key, producing a chain of evidence of what they saw and what they did. So the developer's good reputation is leveraged to make debug-me secure. + If you trust a developer to ship software to your computer, + you can trust them to debug-me. . When you start debug-me without any options, it will connect to a debug-me server, and print out an url that you can give to the developer to get them connected to you. Then debug-me will show you their GnuPG key and who - has signed it. If the developer has a good reputation, you can proceed - to let them type into your console in a debug-me session. Once the - session is done, the debug-me server will email you the signed + has signed it, and will let you know if they are a known developer + of software on your computer. If the developer has a good reputation, + you can proceed to let them type into your console in a debug-me session. + Once the session is done, the debug-me server will email you the signed evidence of what the developer did in the session. . If the developer did do something bad, you'd have proof that they cannot @@ -40,6 +43,7 @@ Extra-Source-Files: debug-me.service debug-me.init debug-me.default + developer-keyring.gpg Executable debug-me Main-Is: debug-me.hs @@ -81,6 +85,7 @@ Executable debug-me , utf8-string (>= 1.0) , network-uri (>= 2.6) , mime-mail (>= 0.4) + , time (>= 1.6) Other-Modules: ControlWindow ControlSocket @@ -90,6 +95,7 @@ Executable debug-me Graphviz Gpg Gpg.Wot + Gpg.Keyring Hash JSON Log @@ -109,6 +115,7 @@ Executable debug-me SessionID Types Val + Verify VirtualTerminal WebSockets diff --git a/developer-keyring.gpg b/developer-keyring.gpg new file mode 100644 index 0000000..9ca0ee1 Binary files /dev/null and b/developer-keyring.gpg differ diff --git a/doc/faq.mdwn b/doc/faq.mdwn index c9b46ea..6884ec0 100644 --- a/doc/faq.mdwn +++ b/doc/faq.mdwn @@ -6,20 +6,28 @@ #### Should I let John Doe connect to my debug-me session? I don't know that guy. -When a developer connects to your debug-me session, it will display -their GnuPG key, and the number of people who have signed it. It will -also list the names of some of those people (the best connected ones). - -If the developer of software you use is connecting to debug-me, -their software documentation might say what their GnuPG key is. Then you -can simply check that the GnuPG key ids match. +When a developer connects to your debug-me session, debug-me will display +their GnuPG key, and information about it, including +the number of people who have signed it. It will also list the names +of some of those people (the best connected ones). + +Suppose you're using Debian, and debug-me says "John Doe is a Debian +developer". Then it's probably safe to let this person connect, +because you already trust this guy implicitly, since you're using software +he develops. + +How does debug-me know that John Doe is a Debian developer? It's checked +that his gpg key is in the keyring at +`/usr/share/debug-me/keyring/a_Debian_developer.gpg`, which is provided by +Debian. Other software projects that are installed on your computer can +also put keyrings in that directory, and then debug-me will be able to +tell then a developer of a project is connecting. If debug-me says that "John Doe is probably a real person", it means that he's connected to the strong set of the GnuPG web of trust. Other people, who certianly are real, have verified his identity. -So even if you don't know his name, it can be safe to let him connect. - -But it's a gut call. If in doubt, don't let the developer connect. +So even if you don't know his name, it can be safe to let him connect, +but if in doubt, don't let him. If debug-me says "identity cannot be verified!", it means that the GnuPG key couldn't be downloaded at all, or the developer is not connected to the @@ -67,6 +75,18 @@ Here's a quick checklist: * Include your GnuPG key id in your project's documentation, so users will know which key is yours. It also helps to sign git tags, tarballs, git commits, etc with your key. +* Make your software package install a gpg keyring of its developers to + /usr/share/debug-me/keyring/. + + A file there named "a_Foo_developer.gpg" + will make debug-me tell the user that "Your Name is a Foo developer." + when you connect to their debug-me session, and so the user will be more + likely to trust you and let you connect. + + For example: + + gpg --export-options export-minimal --export C910D9222512E3C7 > a_Foo_developer.gpg + * When a user has a bug that you need more information to reproduce and understand, ask if they'll use debug-me. diff --git a/doc/index.mdwn b/doc/index.mdwn index 84bc344..14fec93 100644 --- a/doc/index.mdwn +++ b/doc/index.mdwn @@ -20,19 +20,21 @@ problem. Making your problem their problem gets it fixed fast. A debug-me session is logged and signed with the developer's GnuPG key, producing a [[chain of evidence|evidence]] of what they saw and what they did. So the developer's good reputation is leveraged to make debug-me -secure. +secure. If you trust a developer to ship software to your computer, +you can trust them to debug-me. When you start debug-me without any options, it will connect to a debug-me [[server|servers]], and print out an url that you can give to the developer -to get them connected to you. Then debug-me will show you their GnuPG key -and who has signed it. If the developer has a good reputation, you can +to get them connected to you. Then debug-me will show you their GnuPG key, +who has signed it, and will let you know if they are a known developer +of software on your computer. If the developer has a good reputation, you can proceed to let them type into your console in a debug-me session. Once the session is done, the debug-me server will email you the signed evidence of what the developer did in the session. If the developer did do something bad, you'd have proof that they cannot be trusted, which you can share with the world. Knowing that is the case -will keep most developers honest. +will keep developers honest. diff --git a/doc/todo/use_distribution_keyrings.mdwn b/doc/todo/use_distribution_keyrings.mdwn index df21588..be4492e 100644 --- a/doc/todo/use_distribution_keyrings.mdwn +++ b/doc/todo/use_distribution_keyrings.mdwn @@ -5,3 +5,6 @@ Example output: `Sean Whitton is an official Debian Developer (information accur Distribution packagers of debug-me could add the keyrings to be checked in this way to a configuration file, or possibly just hardcode them somewhere in debug-me's source. --spwhitton + +> [[done]]; you'll need to include the symlinks to the debian keyring +> in the keysafe.deb. --[[Joey]] diff --git a/doc/todo/use_distribution_keyrings/comment_2_43e012511d2fc39d78789541482928b7._comment b/doc/todo/use_distribution_keyrings/comment_2_43e012511d2fc39d78789541482928b7._comment new file mode 100644 index 0000000..8145e47 --- /dev/null +++ b/doc/todo/use_distribution_keyrings/comment_2_43e012511d2fc39d78789541482928b7._comment @@ -0,0 +1,9 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 2""" + date="2017-05-20T21:10:36Z" + content=""" +Simplified that sligtly. The keyring filename can describe the +relationship, eg "a_Debian_developer.gpg". The mtime of the keyring will be +displayed so the user knows how up-to-date it is. +"""]] -- cgit v1.2.3