Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check that GnuPG key import was successful. #148

Merged
merged 1 commit into from
Jul 8, 2016

Conversation

isislovecruft
Copy link
Contributor

Rather than checking the GnuPG process exit code, a more robust way to
handle determining whether or not a GnuPG process behaved as was
intended is to check GnuPG's status-fd output. 0

In the case of key import, the particular status-fd flag we're looking
for is IMPORT_OK followed by a "reason", then the expected
fingerprint. 1 Because the "reason"s are integers which may be ORed,
and we are never expecting private keys to be within the file, we can
assume the reason to be [0, 15] inclusive.

While it's not strictly necessary to hardcode Erinn's key fingerprint
within the code because the keyfiles are safely distributed along with
the source code, doing so adds a simple defense-in-depth mechanism for
the unlikely case that a user's torbrowser-launcher package/source
download was compromised. As such, and because it was a trivial
addition which will also assist with checking that a signature was made
by the key with the expected fingerprint 2, I've gone ahead and added
a common.fingerprints dictionary whose keys match the names of the
common.paths keyfile for their respective key (i.e. the fingerprint
for common.paths['erinn_key'] is stored at
common.fingerprints['erinn_key']) in order to facilitate extensibility
in the event that torbrowser-launcher should add new keyfiles in the
future. This may be removed, if undesirable.

  • ADD common.gnupg_import_ok_pattern, a compiled regex for
    determining if a key import was successful.
  • ADD new class attribute, common.Common.fingerprints for storing
    fingerprints.
  • ADD new method, common.Common.import_key_and_check_status(), which
    imports a GnuPG key, and then checks that the key was successfully
    imported.
  • CHANGE common.Common.import_keys() method to make adding
    new/additional keys easier.
  • FIXES check gpg exit code after gpg key import #137
Rather than checking the GnuPG process exit code, a more robust way to
handle determining whether or not a GnuPG process behaved as was
intended is to check GnuPG's status-fd output. [0]

In the case of key import, the particular status-fd flag we're looking
for is `IMPORT_OK` followed by a "reason", then the expected
fingerprint. [1]  Because the "reason"s are integers which may be ORed,
and we are never expecting private keys to be within the file, we can
assume the reason to be `[0, 15]` inclusive.

While it's not strictly necessary to hardcode Erinn's key fingerprint
within the code because the keyfiles are safely distributed along with
the source code, doing so adds a simple defense-in-depth mechanism for
the unlikely case that a user's torbrowser-launcher package/source
download was compromised.  As such, and because it was a trivial
addition which will also assist with checking that a signature was made
by the key with the expected fingerprint [2], I've gone ahead and added
a `common.fingerprints` dictionary whose keys match the names of the
`common.paths` keyfile for their respective key (i.e. the fingerprint
for `common.paths['erinn_key']` is stored at
`common.fingerprints['erinn_key']`) in order to facilitate extensibility
in the event that torbrowser-launcher should add new keyfiles in the
future.  This may be removed, if undesirable.

 * ADD `common.gnupg_import_ok_pattern`, a compiled regex for
   determining if a key import was successful.
 * ADD new class attribute, `common.Common.fingerprints` for storing
   fingerprints.
 * ADD new method, `common.Common.import_key_and_check_status()`, which
   imports a GnuPG key, and then checks that the key was successfully
   imported.
 * CHANGE `common.Common.import_keys()` method to make adding
   new/additional keys easier.
 * FIXES torproject#137

[0]: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;hb=HEAD#l323
[1]: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;hb=HEAD#l713
[2]: torproject#147
isislovecruft added a commit to isislovecruft/torbrowser-launcher that referenced this pull request Oct 27, 2014
 * ADDS two compiled regexes, `launcher.gnupg_goodsig_pattern` and
   `launcher.gnupg_validsig_pattern`.
 * CHANGE the signature validity check in `Launcher.verify()` to be more
   robust and accurate.
 * ADD check that the signature was created by the key with fingerprint
   which we expected it to be from.
 * FIXES torproject#147

NOTE: This patch depends upon some of the changes in my previous patch
      for issue torproject#137 (pull request torproject#148) in commit
      b337b3d.
@isislovecruft
Copy link
Contributor Author

Ah, someone should also check if this works on Windows. Sometimes parts of the Python subprocess module hate on Windows users.

@micahflee
Copy link
Collaborator

Thank you @isislovecruft! Sorry for taking so long, reviewing and merging now.

@micahflee
Copy link
Collaborator

If I delete all of the TBL files (rm -r ~/.local/share/torbrowser/ ~/.cache/torbrowser/ ~/.config/torbrowser/) and then run torbrowser-launcher for the first time, I get this:

Creating GnuPG homedir /home/micah/.local/share/torbrowser/gnupg_homedir
Importing keys
Could not import key with fingerprint: 8738A680B84B3031A630F2DB416F061063FEE659.
Not all keys were imported successfully!

However the key does indeed get imported successfully, and it verifies the signature successfully after downloading TBB.

If I run torbrowser-launcher a second time I get:

Importing keys
Successfully imported all keys.

It looks like when I run it just after deleting all of the TBL files, this is the output:

gpg: keyring `/home/micah/.local/share/torbrowser/gnupg_homedir/secring.gpg' created
gpg: keyring `/home/micah/.local/share/torbrowser/gnupg_homedir/pubring.gpg' created
gpg: /home/micah/.local/share/torbrowser/gnupg_homedir/trustdb.gpg: trustdb created
gpg: key 63FEE659: public key "Erinn Clark <erinn@torproject.org>" imported
[GNUPG:] IMPORTED 416F061063FEE659 Erinn Clark <erinn@torproject.org>
[GNUPG:] IMPORT_OK 1 8738A680B84B3031A630F2DB416F061063FEE659
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
[GNUPG:] IMPORT_RES 1 0 1 1 0 0 0 0 0 0 0 0 0 0

And when I run it a second time, this is the output:

[GNUPG:] IMPORT_OK 0 8738A680B84B3031A630F2DB416F061063FEE659
gpg: key 63FEE659: "Erinn Clark <erinn@torproject.org>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
[GNUPG:] IMPORT_RES 1 0 0 0 1 0 0 0 0 0 0 0 0 0

I think the regex is only checking the first line of output, not the first "[GNUPG:]" line.

@micahflee micahflee closed this Nov 1, 2015
@micahflee micahflee reopened this Jul 8, 2016
@micahflee
Copy link
Collaborator

A year and a half late merging a pull request is better than never, right?

@micahflee micahflee merged commit b337b3d into torproject:master Jul 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants