DataDog / yubikey

YubiKey at Datadog
MIT License
495 stars 36 forks source link

Issue with PIN not being typed #50

Closed donferi closed 3 years ago

donferi commented 4 years ago

I'm trying to get this awesome setup working but when running ./gpg.sh it hangs when trying to change the PIN. It correctly selects the option 1 but then it never types the pin, after it timesout I can see the 123456.

Eg:

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
gpg: OpenPGP card no. <redacted> detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
Please enter the PIN
PIN:
Error changing the PIN: Timeout

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 123456

I tried bumping the sleep in expect.sh to 1, switching from zsh to bash, but I can't seem to figure out what is going on, I can't get it to type it at the right time.

Any help would be greatly appreciated.

trishankatdatadog commented 4 years ago

Try running expect in debug mode (pass the -d flag to the command in expect.sh), and see what the output tells you. Specifically, look for what observed output doesn't match the expected output...

https://wiki.tcl-lang.org/page/Debugging+Expect+programs

donferi commented 4 years ago

Interesting, it seems like it's not matching the PIN: until the nError changing the PIN: 🤔

expect: does "passwd\r\ngpg: OpenPGP card no. <num> detected\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\n" (spawn_id exp8) match exact string "Your selection? "? no
Your selection?
expect: does "passwd\r\ngpg: OpenPGP card no. <num> detected\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\nYour selection? " (spawn_id exp8) match exact string "Your selection? "? yes
expect: set expect_out(0,string) "Your selection? "
expect: set expect_out(spawn_id) "exp8"
expect: set expect_out(buffer) "passwd\r\ngpg: OpenPGP card no. <num> detected\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\nYour selection? "
send: sending "1\r" to { exp8 }

expect: does "" (spawn_id exp8) match exact string "PIN: "? no
1

expect: does "1\r\n" (spawn_id exp8) match exact string "PIN: "? no
Please enter the PIN
PIN:
Error changing the PIN: Timeout

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

expect: does "1\r\nError changing the PIN: Timeout\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\n" (spawn_id exp8) match exact string "PIN: "? yes
expect: set expect_out(0,string) "PIN: "
expect: set expect_out(spawn_id) "exp8"
expect: set expect_out(buffer) "1\r\nError changing the PIN: "
send: sending "123456\r" to { exp8 }

expect: does "Timeout\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\n" (spawn_id exp8) match exact string "PIN: "? no
Your selection? 123456
trishankatdatadog commented 4 years ago

I'm sorry, but without knowing more about your setup or carefully looking through your output, it's hard to tell exactly what's happening.

As a temporary workaround, I recommend running the commands in the expect script manually. Sorry about that.

daisukixci commented 4 years ago

@donferi can you try to add a sleep 1 line 87 in expect.sh ?

donferi commented 4 years ago

@daisukixci Thanks for the help! Tried it out and got the same issue, seems like it's not sending the keys until the next expect operation, but that doesn't make a lot of sense 😂

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

expect: does "passwd\r\ngpg: OpenPGP card no. <num> detected\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\n" (spawn_id exp8) match exact string "Your selection? "? no
Your selection?
expect: does "passwd\r\ngpg: OpenPGP card no. <num> detected\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\nYour selection? " (spawn_id exp8) match exact string "Your selection? "? yes
expect: set expect_out(0,string) "Your selection? "
expect: set expect_out(spawn_id) "exp8"
expect: set expect_out(buffer) "passwd\r\ngpg: OpenPGP card no. <num> detected\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\nYour selection? "
send: sending "1\r" to { exp8 }
Sleeping for 5 seconds

expect: does "" (spawn_id exp8) match exact string "PIN: "? no
1

expect: does "1\r\n" (spawn_id exp8) match exact string "PIN: "? no
Please enter the PIN
PIN:
Error changing the PIN: Timeout

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

expect: does "1\r\nError changing the PIN: Timeout\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\n" (spawn_id exp8) match exact string "PIN: "? yes
expect: set expect_out(0,string) "PIN: "
expect: set expect_out(spawn_id) "exp8"
expect: set expect_out(buffer) "1\r\nError changing the PIN: "
send: sending "123456\r" to { exp8 }

expect: does "Timeout\r\n\r\n1 - change PIN\r\n2 - unblock PIN\r\n3 - change Admin PIN\r\n4 - set the Reset Code\r\nQ - quit\r\n\r\n" (spawn_id exp8) match exact string "PIN: "? no
Your selection? 123456
daisukixci commented 4 years ago

Will take a look this weekend

daisukixci commented 4 years ago

I haven't been able to reproduce with my keys. Can you share a bit of your configuration (hardware, OS and shell used). Can you share the all output please ?

In the meantime can you try with this expect.sh version

#!/usr/bin/env expect
#
# This Expect script was generated by autoexpect on Wed Aug  1 17:10:59 2018
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script.  It
# necessarily has to guess about certain things.  Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts.  If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character.  This
# pacifies every program I know of.  The -c flag makes the script do
# this in the first place.  The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 1  ;# set to 1 to force conservative mode even if
              ;# script was not run conservatively originally
if {$force_conservative} {
    set send_slow {1 .1}
    proc send {ignore arg} {
        sleep .1
        exp_send -s -- $arg
    }
}

#
# 2) differing output - Some programs produce different output each time
# they run.  The "date" command is an obvious example.  Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer.  If this causes a problem, delete these patterns or replace
# them with wildcards.  An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt).  The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don

set timeout -1
match_max 100000

# https://stackoverflow.com/a/17060172
set TOUCH_POLICY  [lindex $argv 0];
set PUK           [lindex $argv 1];
set GPG_HOMEDIR   [lindex $argv 2];
set PIN           [lindex $argv 3];
set KEY_LENGTH    [lindex $argv 4];
set REALNAME      [lindex $argv 5];
set EMAIL         [lindex $argv 6];
set COMMENT       [lindex $argv 7];

# Turn off OTP.
send_user "Turning off YubiKey OTP:\n"
spawn ykman mode "FIDO+CCID"
expect {
  "Mode is already FIDO+CCID, nothing to do..." {
    expect eof
  }

  ": " {
    send -- "y\r"
    expect eof
  }
}

# Set up PIN, PUK, and then generate keys on card.

send_user "Now generating your GPG keys on the YubiKey itself.\n"
spawn gpg --homedir=$GPG_HOMEDIR --card-edit

expect -exact "gpg/card> "
send -- "admin\r"
# https://developers.yubico.com/PGP/Card_edit.html

sleep 2
expect -exact "gpg/card> "
send -- "passwd\r"

sleep 2
# Change PIN
expect -exact "Your selection? "
send -- "1\r"

sleep 2
# Default PIN
expect -exact "PIN: "
send -- "123456\r"

sleep 2
# New PIN
expect -exact "PIN: "
send -- "$PIN\r"

sleep 2
# Repeat new PIN
expect -exact "PIN: "
send -- "$PIN\r"

sleep 2
# Change PUK
expect -exact "Your selection? "
send -- "3\r"

sleep 2
# Default PUK
expect -exact "Admin PIN: "
send -- "12345678\r"

sleep 2
# New PUK
expect -exact "Admin PIN: "
send -- "$PUK\r"

sleep 2
# Repeat new PUK
expect -exact "Admin PIN: "
send -- "$PUK\r"

sleep 2
# Get out of passwd menu
expect -exact "Your selection? "
send -- "q\r"

# Set desired key attributes.

expect -exact "gpg/card> "
send -- "key-attr\r"

# Signature key.
expect -exact "Your selection? "
# RSA
send -- "1\r"

expect "What keysize do you want? (*) "
send -- "$KEY_LENGTH\r"

# Send new PUK
expect -exact "Admin PIN: "
send -- "$PUK\r"

# Encryption key.
expect -exact "Your selection? "
# RSA
send -- "1\r"

expect "What keysize do you want? (*) "
send -- "$KEY_LENGTH\r"

# Send new PUK
expect -exact "Admin PIN: "
send -- "$PUK\r"

# Authentication key.
expect -exact "Your selection? "
# RSA
send -- "1\r"

expect "What keysize do you want? (*) "
send -- "$KEY_LENGTH\r"

# Send new PUK
expect -exact "Admin PIN: "
send -- "$PUK\r"

# Time to generate.

expect -exact "gpg/card> "
send -- "generate\r"

expect -exact "Make off-card backup of encryption key? (Y/n) "
send -- "n\r"

# Send new PIN
expect -exact "PIN: "
send -- "$PIN\r"

expect -exact "Key is valid for? (0) "
send -- "10y\r"

expect -exact "Is this correct? (y/N) "
send -- "y\r"

expect -exact "Real name: "
send -- "$REALNAME\r"

expect -exact "Email address: "
send -- "$EMAIL\r"

expect -exact "Comment: "
send -- "$COMMENT\r"

expect -exact "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
send -- "O\r"

# Send new PUK
expect -exact "Admin PIN: "
send -- "$PUK\r"

send_user "\nNow generating keys on card, lights will be flashing, this will take a few minutes, please wait...\n"

expect -exact "gpg/card> "
send -- "quit\r"

expect eof

# Turn on touch for SIGNATURES.

send_user "Now requiring you to touch your Yubikey to sign any message.\n"
spawn ykman openpgp set-touch sig $TOUCH_POLICY

expect -exact "Enter admin PIN: "
stty -echo
send -- "$PUK\r"

expect -exact "Set touch policy of signature key to $TOUCH_POLICY? \[y/N\]: "
send -- "y\r"
expect eof

# Turn on touch for AUTHENTICATION.

send_user "Now requiring you to touch your Yubikey to authenticate SSH.\n"
spawn ykman openpgp set-touch aut on

expect -exact "Enter admin PIN: "
stty -echo
send -- "$PUK\r"

expect -exact "Set touch policy of authentication key to on? \[y/N\]: "
send -- "y\r"
expect eof

# Turn on touch for ENCRYPTION.

send_user "Now requiring you to touch your Yubikey to encrypt any message.\n"
spawn ykman openpgp set-touch enc on

expect -exact "Enter admin PIN: "
stty -echo
send -- "$PUK\r"

expect -exact "Set touch policy of encryption key to on? \[y/N\]: "
send -- "y\r"
expect eof

# Touch for ATTESTATION works only for Yubico firmware >= 5.2.3.
# https://support.yubico.com/support/solutions/articles/15000027139-yubikey-5-2-3-enhancements-to-openpgp-3-4-support
trishankatdatadog commented 4 years ago

Best to read his debug log or do a remote Zoom debugging session, I think...

donferi commented 4 years ago

Sorry for the late response, I'd be down for a Zoom / vscode remote debugging session. I'm on CST (GMT -6) timezone. I could do anytime as long is not in the middle of the night. Or I could post more info here, whatever you guys prefer 👍

daisukixci commented 4 years ago

Sorry for the long term issue :(, GPG has new version and we updated the expect script to make it compatible, @donferi are you able to test the new version available in https://github.com/DataDog/yubikey/pull/61

donferi commented 4 years ago

@daisukixci Thanks for the reply! Unfortunately I'm still getting the same issue.

daisukixci commented 3 years ago

@donferi can you try to add set stty_init -echo to line 19 of expect.sh and try to run gpg.sh :man-bowing:

EDIT: made a branch https://github.com/DataDog/yubikey/pull/68 so you just have to checkout in it

daisukixci commented 3 years ago

@donferi a DD user find a way to fix similar error on his laptop, can you try to run the script this way GPG_TTY="" ./gpg.sh