NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.31k stars 14.27k forks source link

Failed to authenticate with gpg on ssh session with initrd gpgcard option activated #106563

Open reyman opened 3 years ago

reyman commented 3 years ago

Describe the bug

Actually on unstable, it seems impossible to forward GPG agent to a remote ssh from a yubikey.

To Reproduce

Install Nixos from liveCD

  1. with GPG config activated for luks decryption :
boot.initrd.luks.gpgSupport = true;

boot.initrd.luks.devices = {
          "enc-pv" = {
            name = "enc-pv";
            preLVM = true;
            device = "$luksuuid";
            gpgCard = {
              publicKey = ./gpg-yubikey.asc;
              encryptedPass = ./luks-passphrase.asc;
            };
            allowDiscards = true;
          };

2 - with ssh support at initrd for decrypting luks

        boot.initrd.network = {
          enable = true;
          ssh = {
            enable = true;
            port = 2222;
            authorizedKeys = ["<<pubkey()>>"];
            hostKeys = [ "/host_ecdsa_key" ];
            };
        };

3 - Modify local config to connect on my server with remote forwarding

Found this information for .gnupg configuration into Luksroot.nix at line 124

    ${optionalString luks.gpgSupport ''
    export GPG_TTY=$(tty)
    export GNUPGHOME=/crypt-ramfs/.gnupg
    gpg-agent --daemon --scdaemon-program $out/bin/scdaemon > /dev/null 2> /dev/null
    ''}

So after veryfing with gpgconf --list-dirs my socket, i configure my local .ssh/config like that

Host myhost
  Hostname xxx.xxx.xxx.xxx
  User root
  StreamLocalBindUnlink yes
  IdentityFile ~/.ssh/id_rsa_yubikey.pub
  RemoteForward /crypt-ramfs/.gnupg/S.gpg-agent /run/user/1000/gnupg/S.gpg-agent

4 - Reboot and try to authenticate with my Yubikey GPG smartcard uing ssh

Authenticated to xx.xx.xx.xx ([xx.xx.xx.xx]:2222).
debug1: Remote connections from /crypt-ramfs/.gnupg/S.gpg-agent:-2 forwarded to local address /run/user/1000/gnupg/S.gpg-agent:-2
debug3: send packet: type 80
debug1: channel 0: new [client-session]
debug3: ssh_session2_open: channel_new: 0
debug2: channel 0: send open
debug3: send packet: type 90
debug1: Requesting no-more-sessions@openssh.com
debug3: send packet: type 80
debug1: Entering interactive session.
debug1: pledge: exec
debug3: receive packet: type 80
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug3: receive packet: type 4
debug1: Remote: /root/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
debug3: receive packet: type 4
debug1: Remote: /root/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
debug3: receive packet: type 82
debug1: remote forward failure for: listen /crypt-ramfs/.gnupg/S.gpg-agent:-2, connect /run/user/1000/gnupg/S.gpg-agent:-2
Warning: remote port forwarding failed for listen path /crypt-ramfs/.gnupg/S.gpg-agent
debug1: All remote forwarding requests processed

Failed ..

5- So i remove all the S* Socket on remote /crypt-ramfs/.gnupg and after that i connect with success ...

debug1: Authentication succeeded (publickey).
Authenticated to xx.xx.xx.xx ([xx.xx.xx.xx]:2222).
debug1: Remote connections from /crypt-ramfs/.gnupg/S.gpg-agent:-2 forwarded to local address /run/user/1000/gnupg/S.gpg-agent:-2
debug3: send packet: type 80
debug1: channel 0: new [client-session]
debug3: ssh_session2_open: channel_new: 0
debug2: channel 0: send open
debug3: send packet: type 90
debug1: Requesting no-more-sessions@openssh.com
debug3: send packet: type 80
debug1: Entering interactive session.
debug1: pledge: exec
debug3: receive packet: type 80
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug3: receive packet: type 4
debug1: Remote: /root/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
debug3: receive packet: type 4
debug1: Remote: /root/.ssh/authorized_keys:1: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding
debug3: receive packet: type 81
debug1: remote forward success for: listen /crypt-ramfs/.gnupg/S.gpg-agent:-2, connect /run/user/1000/gnupg/S.gpg-agent:-2
debug1: All remote forwarding requests processed

When i check on remote host, in ash using ps -a :

  275 root      0:00 gpg-agent --daemon --scdaemon-program /bin/scdaemon
  279 root      0:00 scdaemon --multi-server --homedir /crypt-ramfs/.gnupg

Ok, there is some problem with created socket at initialization of initrd, but that don't explain why during boot GPG card don't appear and gpg --card-status don't work !

// Trying to debug by trying to run manually gpg --card-status

1 - on remote, add log to gpg-agent, first kill gpg-agent :

/crypt-ramfs/.gnupg # killall gpg-agent || true

2a - add this into /crypt-ramfs/.gnupg/gpg-agent.conf

debug-level guru
debug-all
log-file /crypt-ramfs/.gnupg/mygpglogfile.log

2b - add debug info to /crypt-ramfs/.gnupg/scdaemon.conf

debug-level guru
debug-all                            
debug-ccid-driver                    
log-file /crypt-ramdfs/.gnupg/scd.log 

3 - reload

/crypt-ramfs/.gnupg # gpg-agent --homedir /crypt-ramfs/.gnupg --daemon --scdaemon-program /bin/scdaemon

4 Reconnect with ssh and see nothing happen into log :

/crypt-ramfs/.gnupg # cat mygpglogfile.log 
2020-12-10 16:02:41 gpg-agent[397] listening on socket '/crypt-ramfs/.gnupg/S.gpg-agent'
2020-12-10 16:02:41 gpg-agent[397] listening on socket '/crypt-ramfs/.gnupg/S.gpg-agent.extra'
2020-12-10 16:02:41 gpg-agent[397] listening on socket '/crypt-ramfs/.gnupg/S.gpg-agent.browser'
2020-12-10 16:02:41 gpg-agent[397] listening on socket '/crypt-ramfs/.gnupg/S.gpg-agent.ssh'
2020-12-10 16:02:41 gpg-agent[398] gpg-agent (GnuPG) 2.2.23 started
2020-12-10 16:02:45 gpg-agent[398] DBG: agent_cache_housekeeping
2020-12-10 16:02:49 gpg-agent[398] DBG: agent_cache_housekeeping
2020-12-10 16:02:53 gpg-agent[398] DBG: agent_cache_housekeeping

6 - Trying to run manually gpg --card-status on remote ash and see the problems

~ # gpg --card-status
gpg: failed to start agent '/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-gnupg-2.2.23/bin/gpg-agent': No such file or directory
gpg: can't connect to the agent: No such file or directory
gpg: OpenPGP card not available: No agent running

Using lsof and which i see that running PID for gpg / scadaemon :

which gpg-agent return

/nix/store/gf17pa61cwvf41xggq3q8cv6wrw46jaq-extra-utils/bin/gpg-agent

lsof -p PID of the current running gpg-agent return

/nix/store/gf17pa61cwvf41xggq3q8cv6wrw46jaq-extra-utils/bin/gpg-agent
/nix/store/gf17pa61cwvf41xggq3q8cv6wrw46jaq-extra-utils/bin/scdaemon

My conclusion at this time :

Expected behavior

Decrypt my luks filesystem using my gpg smartcard by SSH with GPG remote forwarding

Notify maintainers @marenz2569 @flokli @colemickens

Maintainer information:

# a list of nixpkgs attributes affected by the problem
attribute:
# a list of nixos modules affected by the problem
module: system/boot/luksroot
nixos-discourse commented 3 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/yubikey-smartcard-challenge-mode-usable-on-remote-ssh/8936/32

reyman commented 3 years ago

Ok i found a weird way to get gpg --card-status working :

1 - connect to remote initrd ssh 2 - remove all socket ~/crypt-ramfs/.gnupg 2 - pkill gpg-agent 2 - disconnect 3 - reconnect 4 - search the good gpg package with which gpg 5 - run the gpg with good homedir :

/nix/store/gf17pa61cwvf41xggq3q8cv6wrw46jaq-extra-utils/bin/gpg --homedir /crypt-ramfs/.gnupg --card-status

Each time you need to pkill gpg-agent and rm /crypt-ramfs/gnupg/S* , disconnect, reconnect when you re running this command... If you don't do that, you have this error :

~ #  /nix/store/gf17pa61cwvf41xggq3q8cv6wrw46jaq-extra-utils/bin/gpg --homedir /crypt-ramfs/.gnupg --card-status
gpg: failed to start agent '/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-gnupg-2.2.23/bin/gpg-agent': No such file or directory
gpg: can't connect to the agent: No such file or directory
gpg: OpenPGP card not available: No agent running

Works manually to decrypt passphrase, but don't resolve the problem of "No gpg Card to appear...." during initrd boot.

nixos-discourse commented 3 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/yubikey-smartcard-challenge-mode-usable-on-remote-ssh/8936/33

colemickens commented 3 years ago

Actually on unstable, it seems impossible to forward GPG agent to a remote ssh from a yubikey. I used this, gpg forwarding, about an hour ago. There might be something complicated about using GPG with luksroot, but there's nothing broken about just forwarding a gpg socket on unstable.

colemickens commented 3 years ago

And to reiterate, again, gpg --card-status is not meant or expected to work with a forwarded gpg socket.

reyman commented 3 years ago

And to reiterate, again, gpg --card-status is not meant or expected to work with a forwarded gpg socket.

Hum, i'm only talking about the initrd first stage and only that, so using a specific env (initrd stage) with very limited capacity, before classic and normal nixos environment with gpg normally configured. To be more clear, this radically different from nixos final stage.

Sorry about that, like multiple people, i'm trying, and i'm not alone. gpg --card-status with gpg-agent.socket forwarding (and not the limited gpg-agent-extra.socket) seems possible, and there are multiple post on web explaining that, for example : https://blog.alt255.com/post/gpg_forwarding/

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

reyman commented 3 years ago

Sorry but this is not solved Bot.

sergei-mironov commented 2 years ago

Just faced into the similar issue while trying to create a key, and it's horrible. Ok, I'm on nixos-21.05 and can confirm that I see an invalid pinentry path in the gpgconf's output and also that gpg starts another version of gpg-agent with no --pinentry-program flag used by systemd of nixos.

Here is a quick workaround that I am using to generate the damn gpg key:

  1. Install pinentry manually, write down the full path to the pinentry
  2. Run gpg-daemon in a daemon-shell mode. For me it seems important to
    • Switch the TERM to linux (I used xterm-kitty)
    • Set LANG=C to disable the localization because I would otherwise get a repeating 'Enter your password' window Here is the command:
      $ TERM=linux LANG=C gpg-agent --pinentry-program /nix/store/297r9wmbsd0n51bx155dml93bdirn87p-pinentry-1.1.0/bin/pinentry  --daemon /bin/sh
  3. The agent will the open a shell where the environment is set correctly so I could call run a task which requires passwords, e.g. gpg --yes --quick-gen-key 'Me <email@ser.org>' default default never
    • But gpgconf --check-programs still outputs incorrect path for pinentry, thinking that it is in the gpg's root
colemickens commented 2 years ago

Just throwing this out again -- when I walk up to a computer and need to do GPG/SSH stuff, I run gpg-fix: https://github.com/cole-mickens/nixcfg/blob/063d1b16a7b9bd676805350511a4e9d78ce0d529/pkgs/commands.nix#L56

I basically never encounter this problem anymore as the script ensures the user service is restarted instead of gpg-agent self-daemonizing. It sort of feels like there should be a way to tell gpg-agent to please kindly not, but I haven't looked into it (I'm more interested in soon putting GPG entirely behind me other than for compat)