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

Refactor PIN/passphrase handling #211

Merged
merged 6 commits into from
Mar 10, 2018
Merged

Refactor PIN/passphrase handling #211

merged 6 commits into from
Mar 10, 2018

Conversation

romanz
Copy link
Owner

@romanz romanz commented Mar 1, 2018

This should allow easier integration of custom PIN/passphrase entry tools (e.g. #202).

@romanz
Copy link
Owner Author

romanz commented Mar 1, 2018

@rendaw Could you please take a look?
This should hopefully make the integration of trezor-gpg-pinentry-tk easier :)


def main():
"""Use GPG pinentry program to interact with the user."""
args = ['pinentry']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make this configurable?

With the module name it's a bit more complex since it adds a second layer of configuration. It might need to be an absolute path too in some circumstances since PATH is empty in cron, systemd, etc.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right...
I have added an option to pass arguments to configure the actual binary that is executed by pinetry_gpg.py at 1a50d0a.

expect(p, [b'OK'])

desc = sys.stdin.read().encode('ascii')
write(p, b'SETDESC ' + libagent.gpg.agent.serialize(desc) + b'\n')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh awesome, I should have known you already had a function for this.

@rendaw
Copy link
Contributor

rendaw commented Mar 2, 2018

This looks really good, and thanks for doing this! I realize the pinentry thing isn't that important if you have a keypad, but I'm out of luck there.

Just one comment about configuring the passphrase program.

I'll make a separate PR for docs after this is merged.

@rendaw
Copy link
Contributor

rendaw commented Mar 2, 2018

This should hopefully make the integration of trezor-gpg-pinentry-tk easier :)

Haha, right! Sorry, I don't mean to be dropping links to my own project. Until someone makes a nicer alternative I figure it's helpful though.

@rendaw
Copy link
Contributor

rendaw commented Mar 2, 2018

Sorry, just noticed one other thing. With the normal GPG agent, information about the environment (DISPLAY, TTY, etc) are passed to the pinentry via OPTIONs since the initiator's DISPLAY/TTY are often different than those of the agent.

I couldn't find any information in the gpg-agent/pinentry assuan specs about what values should be forwarded unfortunately. I thought forwarding everything might be okay - if the pinentry doesn't understand the option it will ignore it I believe. Just sending the display/tty ones might be okay too.

Relatedly, gpg2 also adds the --display flag to the pinentry when it starts it. I don't think this is documented either and I don't know which one is preferred for determining the X11 display to show the pinentry on.

@romanz
Copy link
Owner Author

romanz commented Mar 4, 2018

Thanks for the review!
Regarding the DISPLAY/TTY: I tried to run it without passing any OPTION to the underlying pinentry, and it seems to work correctly - so I haven't add the relevant code for passing the display-related options (mainly to keep the code simpler).

@rendaw
Copy link
Contributor

rendaw commented Mar 5, 2018

I agree it's much simpler, and I don't know a good way to integrate it easily. Aside from passing the data between processes you also have to funnel it through all the functions.

I tried it out and I think it has issues in a couple situations as it is now though:

  1. If you use pinentry-tty it will fail (always). pinentry-tty reads/writes to the tty passed with the ttyname option, but falls back to stdin/stdout if ttyname isn't present. Since stdin/stdout are the pipe to gpg-agent it prints the prompt there and the pin entry routine fails.

    log:

      File "/home/andrew/temp/ren/trezor-agent/libagent/device/ui/pinentry_gpg.py", line 32, in expect
        raise ValueError('Unexpected response: {}'.format(resp))
    ValueError: Unexpected response: b'Use the numeric keypad to describe number positions.\n'
    
  2. If you start the gpg agent when DISPLAY isn't set (bootup, init.d/systemd script) and use a graphical pinentry (pinentry-qt, pinentry-gtk, etc) the pinentry returns the line S ERROR qt.isatty 83918950 or similar. This occurs even if you call GPG from a graphical desktop:

    gpg-agent.conf:

    pin-entry-module pinentry_gpg pinentry-qt
    
    $ echo $GNUPGHOME
    /home/rendaw/.gnupg/trezor
    $ echo $DISPLAY
    :0
    $ gpg --sign ~/a.txt
    gpg: Warning: not using 'rendaw' as default key: No secret key
    gpg: all values passed to '--default-key' ignored
    gpg: keydb_search failed: Broken pipe
    gpg: no default secret key: Broken pipe
    gpg: signing failed: Broken pipe

    log:

      File "/home/andrew/temp/ren/trezor-agent/libagent/device/ui/pinentry_gpg.py", line 32, in expect
        raise ValueError('Unexpected response: {}'.format(resp))
    ValueError: Unexpected response: b'S ERROR qt.isatty 83918950 \n'
    

I think 1 is particularly important since otherwise the pinentry won't be usable on systems with no desktop environment (ex: servers).

@romanz
Copy link
Owner Author

romanz commented Mar 6, 2018

Good points... thanks for the testing!
I'll update this PR to solve both issues.

@romanz
Copy link
Owner Author

romanz commented Mar 7, 2018

@rendaw Please take a look :)
The code should now work in a desktop-less environment (by using pinentry-curses):
image

(use sudo update-alternatives --config pinentry to test it in action)

@rendaw
Copy link
Contributor

rendaw commented Mar 7, 2018

This looks really good 👍 . So for GPG it passes options, and for SSH it uses the environment? That seems like the best option given the SSH protocol I think.

I'll try it out tomorrow but I doubt I'll have much else to say :)

@rendaw
Copy link
Contributor

rendaw commented Mar 8, 2018

Ah, it looks like it might not be possible to change pin_entry_binary and passphrase_entry_binary any more in the latest revision.

@romanz
Copy link
Owner Author

romanz commented Mar 8, 2018

Oops... you're right!
Will add soon.

@romanz romanz force-pushed the refactor-pinentry branch 2 times, most recently from 6236822 to 4782aa2 Compare March 8, 2018 15:32
@romanz
Copy link
Owner Author

romanz commented Mar 8, 2018

I've added the following command-line flags to SSH and GPG tools:

  --pin-entry-binary PIN_ENTRY_BINARY
                        Path to PIN entry UI helper.
  --passphrase-entry-binary PASSPHRASE_ENTRY_BINARY
                        Path to passphrase entry UI helper.

Please take a look :)

@rendaw
Copy link
Contributor

rendaw commented Mar 9, 2018

This works great for me! I didn't try reinitializing the gpg part but I added the flags to run-agent.sh and GPG and SSH both work.

I'll get started on documentation updates.

@romanz romanz merged commit 0c9fc33 into master Mar 10, 2018
@romanz
Copy link
Owner Author

romanz commented Mar 10, 2018

Many thanks for the idea, the code and the testing!

@romanz romanz deleted the refactor-pinentry branch March 10, 2018 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants