Yubico / pam-u2f

Pluggable Authentication Module (PAM) for U2F and FIDO2
https://developers.yubico.com/pam-u2f/
BSD 2-Clause "Simplified" License
542 stars 78 forks source link

Possible way to disable requirement to touch device? #149

Closed rolandog closed 4 years ago

rolandog commented 4 years ago

Hello. First, I'd like to thank the Yubico developers for such great work on the pam-u2f module.

I'm writing this issue because I'm trying to implement a PAM authentication flow similar to what is seen in websites:

Although I've been reading several resources online, I haven't been able to create something that feels entirely correct.

At first, I wanted to give the user some choice, and I dabbled unsuccessfully with the pam_exec.so module (but found that it couldn't request user input to allow choosing which 2FA option to use). Also, this particular answer on ServerFault dissuaded me from using [success=1 default=ignore] pam_u2f.so on the first line.

Then, I cobbled together something that looks and performs similar to the above requirements (with the limitation of having to press two times the tactile trigger):

# What the following lines accomplish:
#     Prompt for a U2F device, if one isn't inserted.
#     In case the U2F device is known, prompt for us to press the button twice.
#     In case the U2F device is not know, prompt for a verification code from Google Authenticator.
#     Allow users that are not configured to use U2F or Google Authenticator to log in.
auth       [success=1 new_authtok_reqd=ok ignore=ignore default=ignore]   pam_u2f.so interactive cue nouserok authfile=/etc/Yubico/u2f_keys
auth       [success=1 new_authtok_reqd=ok ignore=ignore default=bad]      pam_google_authenticator.so nullok
auth       required                                                       pam_u2f.so cue nouserok authfile=/etc/Yubico/u2f_keys

On a terminal emulator, this results in the following dialogue:

user@computer:~$ sudo echo "Hello"
[sudo] password for user: 
Insert your U2F device, then press ENTER.
Please touch the device.
Please touch the device.
Hello

(Note: It's most likely that I'm not understanding the proper usage of userpresence and userverification) I tried using userpresence=0 userverification=0 instead of cue on the first auth line, but this still resulted in a flashing Yubikey, which I had to tap twice, although the reminder to touch the device was only displayed once.

So, what I'm trying to ask is: What would be the best way to achieve something that only detects if a (valid?) U2F device is plugged in? (perhaps succeeding on 'check-only' authentication request?).

If such an option were to be called notouching, this would allow the above code to be converted into:

auth       [success=1 new_authtok_reqd=ok ignore=ignore default=ignore]   pam_u2f.so interactive notouching nouserok authfile=/etc/Yubico/u2f_keys
auth       [success=1 new_authtok_reqd=ok ignore=ignore default=bad]      pam_google_authenticator.so nullok
auth       required                                                       pam_u2f.so cue nouserok authfile=/etc/Yubico/u2f_keys

And, in turn, it would allow for not having to request two times that the user touch the device.

a-dma commented 4 years ago

It's not possible to perform authentication operations without a user interaction of some sort. There exist debug commands such as wink and ping, but those are not exposed through the module.

I think the best way is what you are doing, trying to authenticate using the module and reacting to it failing by invoking a different module

a-dma commented 4 years ago

BTW, are you running the released version or are you using the git version?

rolandog commented 4 years ago

Hi @a-dma , thanks for your response! In that case, I think I may change the cue and prompt messages so that the procedure seems more clear to the users.

As for the version, I'm using the released version from Synaptic (currently on Ubuntu 20.04); this would be libpam-u2f (1.0.8-1).

Thank you for your help.

a-dma commented 4 years ago

No problem. The git version, which should be cleaned up a bit and released, uses a different set of dependencies and should allow you to expose the behavior you wanted by setting setting userpresence=0 in the module config file.

If you want to try that I'm more than happy to hear feedback.

rolandog commented 4 years ago

Ah, that totally makes sense (I'm glad I wasn't misreading the documentation); I'll see if tonight I have some time to build the git version and test the behaviour. Thanks for the tip!

a-dma commented 4 years ago

Thank you and sorry for the messy state. I promised a release a long time ago and still haven't gotten around that...

rolandog commented 4 years ago

Hey, don't worry about it (everything is understandable, given the current global state of affairs).

I didn't have time yesterday night to build; today I had some time before heading out, but I stumbled on some unmet dependencies.

I'm writing from my phone, and what I'm writing is from my (sometimes shoddy) memory.

Running ./configure made it apparent that I didn't have libssl-dev and libfido2-dev.

And running make made it apparent that I didn't have gengetopt.

I'll continue documenting in the evening, and update package names that I didn't name correctly.

On Wed, Jul 15, 2020, 12:53 Alessio Di Mauro notifications@github.com wrote:

Thank you and sorry for the messy state. I promised a review a long time ago and still haven't gotten around that...

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/Yubico/pam-u2f/issues/149#issuecomment-658699150, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC6TSHT6HOREDLCNTTUZRFLR3WDDBANCNFSM4OX757LA .

a-dma commented 4 years ago

That looks correct, the current version uses libfido2 instead of libu2f-server and libu2f-host. OpenSSL is used for the base64 encoding and some of the crypto stuff. It goes without saying that the documentation should be updated to reflect the current state.

rolandog commented 4 years ago

Hello. I'm back. I finished the building process; I received some warnings while building (see below section).

Afterwards, I changed the /etc/pam.d/sudo file to contain:

auth       [success=1 new_authtok_reqd=ok ignore=ignore default=ignore]   pam_u2f.so interactive userpresence=0 nouserok authfile=/etc/Yubico/u2f_keys debug
auth       [success=1 new_authtok_reqd=ok ignore=ignore default=bad]   pam_google_authenticator.so nullok
auth       required   pam_u2f.so cue nouserok authfile=/etc/Yubico/u2f_keys

I re-ran pamu2fcfg (because this new version apparently has additional fields), and I removed cue on the first line, because I thought it would be mutually exclusive to userpresence=0.

Afterwards, I ran the following test, which still requested a first touch of the device (although it wasn't apparent because of the lack of a cue message).

Semi-annonimized test and debug log ``` user@computer:~$ sudo echo "hello world" [sudo] password for user: debug(pam_u2f): pam-u2f.c:109 (parse_cfg): called. debug(pam_u2f): pam-u2f.c:110 (parse_cfg): flags 32768 argc 5 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[0]=interactive debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[1]=userpresence=0 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[2]=nouserok debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[3]=authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[4]=debug debug(pam_u2f): pam-u2f.c:114 (parse_cfg): max_devices=0 debug(pam_u2f): pam-u2f.c:115 (parse_cfg): debug=1 debug(pam_u2f): pam-u2f.c:116 (parse_cfg): interactive=1 debug(pam_u2f): pam-u2f.c:117 (parse_cfg): cue=0 debug(pam_u2f): pam-u2f.c:118 (parse_cfg): nodetect=0 debug(pam_u2f): pam-u2f.c:119 (parse_cfg): userpresence=0 debug(pam_u2f): pam-u2f.c:120 (parse_cfg): userverification=-1 debug(pam_u2f): pam-u2f.c:121 (parse_cfg): pinverification=-1 debug(pam_u2f): pam-u2f.c:122 (parse_cfg): manual=0 debug(pam_u2f): pam-u2f.c:123 (parse_cfg): nouserok=1 debug(pam_u2f): pam-u2f.c:124 (parse_cfg): openasuser=0 debug(pam_u2f): pam-u2f.c:125 (parse_cfg): alwaysok=0 debug(pam_u2f): pam-u2f.c:126 (parse_cfg): authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:128 (parse_cfg): authpending_file=(null) debug(pam_u2f): pam-u2f.c:130 (parse_cfg): origin=(null) debug(pam_u2f): pam-u2f.c:131 (parse_cfg): appid=(null) debug(pam_u2f): pam-u2f.c:132 (parse_cfg): prompt=(null) debug(pam_u2f): pam-u2f.c:185 (pam_sm_authenticate): Origin not specified, using "pam://computer" debug(pam_u2f): pam-u2f.c:196 (pam_sm_authenticate): Appid not specified, using the same value of origin (pam://computer) debug(pam_u2f): pam-u2f.c:208 (pam_sm_authenticate): Maximum devices number not set. Using default (24) debug(pam_u2f): pam-u2f.c:226 (pam_sm_authenticate): Requesting authentication for user user debug(pam_u2f): pam-u2f.c:237 (pam_sm_authenticate): Found user user debug(pam_u2f): pam-u2f.c:238 (pam_sm_authenticate): Home directory for user is /home/user debug(pam_u2f): pam-u2f.c:309 (pam_sm_authenticate): Using authentication file /etc/Yubico/u2f_keys debug(pam_u2f): util.c:215 (get_devices_from_authfile): Authorization line: user:KeyHandle1,UserKey1,es256,+presence:KeyHandle2,UserKey2,es256,+presence debug(pam_u2f): util.c:220 (get_devices_from_authfile): Matched user: user debug(pam_u2f): util.c:256 (get_devices_from_authfile): KeyHandle for device number 1: KeyHandle1 debug(pam_u2f): util.c:279 (get_devices_from_authfile): publicKey for device number 1: UserKey1 debug(pam_u2f): util.c:303 (get_devices_from_authfile): COSE type for device number 1: es256 debug(pam_u2f): util.c:324 (get_devices_from_authfile): Attributes for device number 1: +presence debug(pam_u2f): util.c:256 (get_devices_from_authfile): KeyHandle for device number 2: KeyHandle2 debug(pam_u2f): util.c:279 (get_devices_from_authfile): publicKey for device number 2: UserKey2 debug(pam_u2f): util.c:303 (get_devices_from_authfile): COSE type for device number 2: es256 debug(pam_u2f): util.c:324 (get_devices_from_authfile): Attributes for device number 2: +presence debug(pam_u2f): util.c:354 (get_devices_from_authfile): Found 2 device(s) for user user debug(pam_u2f): pam-u2f.c:382 (pam_sm_authenticate): Using file '/var/run/user/1000/pam-u2f-authpending' for emitting touch request notifications Insert your U2F device, then press ENTER. get_key_val: key_len=4 debug(pam_u2f): util.c:527 (do_authentication): Device max index is 1 debug(pam_u2f): util.c:559 (do_authentication): Attempting authentication with device number 1 debug(pam_u2f): util.c:581 (do_authentication): Key handle: KeyHandle1 debug(pam_u2f): util.c:687 (do_authentication): Challenge: vlOINIkTmxQs6qVw68fE/QWROSloBdT3npeT+wjtX78= debug(pam_u2f): util.c:422 (get_authenticators): Working with 1 authenticator(s) debug(pam_u2f): util.c:426 (get_authenticators): Checking whether key exists in authenticator 0 debug(pam_u2f): util.c:436 (get_authenticators): Authenticator path: /dev/hidraw1 [...] hello world ``` I cropped the debug info; but if you need the rest, I'll be happy to post it.

I hope I have been of help to provide some feedback, and I'll be happy to test any modifications; I think I will reopen the bug, as it may seem that userpresence=0 was still requiring interacting.

Warnings while building Warnings while running `make`: ``` CC readpassphrase.o readpassphrase.c: In function ‘readpassphrase’: readpassphrase.c:133:9: warning: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Wunused-result] 133 | (void)write(output, prompt, strlen(prompt)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ readpassphrase.c:152:9: warning: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Wunused-result] 152 | (void)write(output, "\n", 1); | ^~~~~~~~~~~~~~~~~~~~~~ ``` Possible warning from libtool, when running `sudo make install`: ``` libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/sbin" ldconfig -n /lib/x86_64-linux-gnu/security ---------------------------------------------------------------------- Libraries have been installed in: /lib/x86_64-linux-gnu/security If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the '-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable during execution - add LIBDIR to the 'LD_RUN_PATH' environment variable during linking - use the '-Wl,-rpath -Wl,LIBDIR' linker flag - have your system administrator add LIBDIR to '/etc/ld.so.conf' See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- ```
a-dma commented 4 years ago

Thanks for spending the time.

Since you re-ran pamu2fcfg, your authentication file should now look like

user:base64_string,base64_other_string,es256,+presence

if you delete the +presence part (or re-run pamu2fcfg with -P) then you should be able to authenticate without having to touch the device.

rolandog commented 4 years ago

No problem! (And sorry for taking time to get back in touch; I was mostly busy).

I re-generated the u2f_keys file with pamu2fcfg with the -P and -nP flags for my two devices, and ran some tests with one key either plugged or unplugged before testing; the debug logs looked the same for any of the keys, and failed with the following debugging information (falling back to google-authenticator):

user@computer:~$ sudo echo "hello world"
[sudo] password for user: 
debug(pam_u2f): pam-u2f.c:109 (parse_cfg): called.
debug(pam_u2f): pam-u2f.c:110 (parse_cfg): flags 32768 argc 5
debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[0]=interactive
debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[1]=userpresence=0
debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[2]=nouserok
debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[3]=authfile=/etc/Yubico/u2f_keys
debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[4]=debug
debug(pam_u2f): pam-u2f.c:114 (parse_cfg): max_devices=0
debug(pam_u2f): pam-u2f.c:115 (parse_cfg): debug=1
debug(pam_u2f): pam-u2f.c:116 (parse_cfg): interactive=1
debug(pam_u2f): pam-u2f.c:117 (parse_cfg): cue=0
debug(pam_u2f): pam-u2f.c:118 (parse_cfg): nodetect=0
debug(pam_u2f): pam-u2f.c:119 (parse_cfg): userpresence=0
debug(pam_u2f): pam-u2f.c:120 (parse_cfg): userverification=-1
debug(pam_u2f): pam-u2f.c:121 (parse_cfg): pinverification=-1
debug(pam_u2f): pam-u2f.c:122 (parse_cfg): manual=0
debug(pam_u2f): pam-u2f.c:123 (parse_cfg): nouserok=1
debug(pam_u2f): pam-u2f.c:124 (parse_cfg): openasuser=0
debug(pam_u2f): pam-u2f.c:125 (parse_cfg): alwaysok=0
debug(pam_u2f): pam-u2f.c:126 (parse_cfg): authfile=/etc/Yubico/u2f_keys
debug(pam_u2f): pam-u2f.c:128 (parse_cfg): authpending_file=(null)
debug(pam_u2f): pam-u2f.c:130 (parse_cfg): origin=(null)
debug(pam_u2f): pam-u2f.c:131 (parse_cfg): appid=(null)
debug(pam_u2f): pam-u2f.c:132 (parse_cfg): prompt=(null)
debug(pam_u2f): pam-u2f.c:185 (pam_sm_authenticate): Origin not specified, using "pam://computer"
debug(pam_u2f): pam-u2f.c:196 (pam_sm_authenticate): Appid not specified, using the same value of origin (pam://computer)
debug(pam_u2f): pam-u2f.c:208 (pam_sm_authenticate): Maximum devices number not set. Using default (24)
debug(pam_u2f): pam-u2f.c:226 (pam_sm_authenticate): Requesting authentication for user user
debug(pam_u2f): pam-u2f.c:237 (pam_sm_authenticate): Found user user
debug(pam_u2f): pam-u2f.c:238 (pam_sm_authenticate): Home directory for user is /home/user
debug(pam_u2f): pam-u2f.c:309 (pam_sm_authenticate): Using authentication file /etc/Yubico/u2f_keys
debug(pam_u2f): util.c:215 (get_devices_from_authfile): Authorization line: user:KeyHandle1,UserKey1,es256,:KeyHandle1,UserKey2,es256,
debug(pam_u2f): util.c:220 (get_devices_from_authfile): Matched user: user
debug(pam_u2f): util.c:256 (get_devices_from_authfile): KeyHandle for device number 1: KeyHandle1
debug(pam_u2f): util.c:279 (get_devices_from_authfile): publicKey for device number 1: UserKey1
debug(pam_u2f): util.c:303 (get_devices_from_authfile): COSE type for device number 1: es256
debug(pam_u2f): util.c:324 (get_devices_from_authfile): Attributes for device number 1: KeyHandle1,UserKey2,es256,
debug(pam_u2f): util.c:354 (get_devices_from_authfile): Found 1 device(s) for user user
debug(pam_u2f): pam-u2f.c:382 (pam_sm_authenticate): Using file '/var/run/user/1000/pam-u2f-authpending' for emitting touch request notifications
Insert your U2F device, then press ENTER.
get_key_val: key_len=4
debug(pam_u2f): util.c:527 (do_authentication): Device max index is 1
debug(pam_u2f): util.c:559 (do_authentication): Attempting authentication with device number 1
debug(pam_u2f): util.c:581 (do_authentication): Key handle: KeyHandle1
debug(pam_u2f): util.c:687 (do_authentication): Challenge: wjlYq0xTLr+3INTNqqaPrnPema0fq333DiHjv1nsBF8=
debug(pam_u2f): util.c:422 (get_authenticators): Working with 1 authenticator(s)
debug(pam_u2f): util.c:426 (get_authenticators): Checking whether key exists in authenticator 0
debug(pam_u2f): util.c:436 (get_authenticators): Authenticator path: /dev/hidraw5

I think that, when parsing the generated file with the options, the Attributes for the device aren't properly parsed (this may be a separate bug).

I do have one question, though, would registering the keys with pamu2fcfg -P always disable checking for user presence? Or is it just to allow for disabling checking for user presence with the userpresence=0 option?

a-dma commented 4 years ago

Yes there is an issue with how credentials are parsed right now. Some of that logic has been rewritten in the ssh format branch, but that issue is still pending.

Did you leave the tail end of the logs out on purpose? Did you get a "Key not found" error?

Just to be clear, the KeyHandle1, UserKey1, KeyHandle2 and UserKey2 is you redacting the values and not what is actually in the file, right?

If that's the case, could you please try either registering only one device, or making sure that the device you have plugged in is the first of the two (i.e. the one for KeyHandle1) and only that. I can get it to work in that scenario.

I do have one question, though, would registering the keys with pamu2fcfg -P always disable checking for user presence? Or is it just to allow for disabling checking for user presence with the userpresence=0 option?

Neither, the idea is that it's possible to set that flag either at the system level (userpresence=1) or at the credential level (+presence), and that the more "restrictive" setting will take effect. However, that logic is a bit tricky because the currently released version of pam-u2f doesn't have the +presence flag but assumes that behavior. On top of that, not setting a flag is not exactly equivalent to setting it to off, but rather it's equivalent to setting it to its default behavior in the specifications.

rolandog commented 4 years ago

Did you leave the tail end of the logs out on purpose? Did you get a "Key not found" error?

Yes, sorry, I was being cautious to not paste revealing information about the U2F key (because I couldn't easily find in util.c what exactly was being displayed after line 436.

Just to be clear, the KeyHandle1, UserKey1, KeyHandle2 and UserKey2 is you redacting the values and not what is actually in the file, right?

Correct! I've been redacting the Key Handle and User Key (is it safe to disclose them?).

If that's the case, could you please try either registering only one device, or making sure that the device you have plugged in is the first of the two (i.e. the one for KeyHandle1) and only that. I can get it to work in that scenario.

I couldn't get it to work on my end.

I re-ran make clean, autoreconf --install, ./configure, make, and sudo make install just to be on the safe side, then generated the keys for a single device with pamu2fcfg -P > ~/.config/Yubico/u2f_keys, and moved them with sudo mv ~/.config/Yubico/u2f_keys /etc/Yubico/u2f_keys.

Here is the relevant information:

partially redacted `/etc/Yubico/u2f_keys` file ``` user:KeyHandle1,UserKey1,es256, ``` I even tried omitting the last comma, to see if the `Unable to retrieve attributes 1` message would disappear, but the end result was the same.
relevant `/etc/pam.d/sudo` rules ``` auth [success=1 new_authtok_reqd=ok ignore=ignore default=ignore] pam_u2f.so interactive userpresence=0 nouserok authfile=/etc/Yubico/u2f_keys debug auth [success=1 new_authtok_reqd=ok ignore=ignore default=bad] pam_google_authenticator.so nullok auth required pam_u2f.so cue userpresence=1 nouserok authfile=/etc/Yubico/u2f_keys debug ```
partially redacted debug logs ``` user@computer:~$ sudo echo "hello world" [sudo] password for user: debug(pam_u2f): pam-u2f.c:109 (parse_cfg): called. debug(pam_u2f): pam-u2f.c:110 (parse_cfg): flags 32768 argc 5 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[0]=interactive debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[1]=userpresence=0 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[2]=nouserok debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[3]=authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[4]=debug debug(pam_u2f): pam-u2f.c:114 (parse_cfg): max_devices=0 debug(pam_u2f): pam-u2f.c:115 (parse_cfg): debug=1 debug(pam_u2f): pam-u2f.c:116 (parse_cfg): interactive=1 debug(pam_u2f): pam-u2f.c:117 (parse_cfg): cue=0 debug(pam_u2f): pam-u2f.c:118 (parse_cfg): nodetect=0 debug(pam_u2f): pam-u2f.c:119 (parse_cfg): userpresence=0 debug(pam_u2f): pam-u2f.c:120 (parse_cfg): userverification=-1 debug(pam_u2f): pam-u2f.c:121 (parse_cfg): pinverification=-1 debug(pam_u2f): pam-u2f.c:122 (parse_cfg): manual=0 debug(pam_u2f): pam-u2f.c:123 (parse_cfg): nouserok=1 debug(pam_u2f): pam-u2f.c:124 (parse_cfg): openasuser=0 debug(pam_u2f): pam-u2f.c:125 (parse_cfg): alwaysok=0 debug(pam_u2f): pam-u2f.c:126 (parse_cfg): authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:128 (parse_cfg): authpending_file=(null) debug(pam_u2f): pam-u2f.c:130 (parse_cfg): origin=(null) debug(pam_u2f): pam-u2f.c:131 (parse_cfg): appid=(null) debug(pam_u2f): pam-u2f.c:132 (parse_cfg): prompt=(null) debug(pam_u2f): pam-u2f.c:185 (pam_sm_authenticate): Origin not specified, using "pam://computer" debug(pam_u2f): pam-u2f.c:196 (pam_sm_authenticate): Appid not specified, using the same value of origin (pam://computer) debug(pam_u2f): pam-u2f.c:208 (pam_sm_authenticate): Maximum devices number not set. Using default (24) debug(pam_u2f): pam-u2f.c:226 (pam_sm_authenticate): Requesting authentication for user user debug(pam_u2f): pam-u2f.c:237 (pam_sm_authenticate): Found user user debug(pam_u2f): pam-u2f.c:238 (pam_sm_authenticate): Home directory for user is /home/user debug(pam_u2f): pam-u2f.c:309 (pam_sm_authenticate): Using authentication file /etc/Yubico/u2f_keys debug(pam_u2f): util.c:215 (get_devices_from_authfile): Authorization line: user:KeyHandle1,UserKey1,es256, debug(pam_u2f): util.c:220 (get_devices_from_authfile): Matched user: user debug(pam_u2f): util.c:256 (get_devices_from_authfile): KeyHandle for device number 1: KeyHandle1 debug(pam_u2f): util.c:279 (get_devices_from_authfile): publicKey for device number 1: UserKey1 debug(pam_u2f): util.c:303 (get_devices_from_authfile): COSE type for device number 1: es256 debug(pam_u2f): util.c:318 (get_devices_from_authfile): Unable to retrieve attributes 1 debug(pam_u2f): util.c:319 (get_devices_from_authfile): Assuming 'p' (backwards compatibility) debug(pam_u2f): util.c:354 (get_devices_from_authfile): Found 1 device(s) for user user debug(pam_u2f): pam-u2f.c:382 (pam_sm_authenticate): Using file '/var/run/user/1000/pam-u2f-authpending' for emitting touch request notifications Insert your U2F device, then press ENTER. get_key_val: key_len=4 debug(pam_u2f): util.c:527 (do_authentication): Device max index is 1 debug(pam_u2f): util.c:559 (do_authentication): Attempting authentication with device number 1 debug(pam_u2f): util.c:581 (do_authentication): Key handle: KeyHandle1 debug(pam_u2f): util.c:687 (do_authentication): Challenge: SaeeVYXzOxV77GamG04TXSjip1o5k1czuIPHDtCJHuQ= debug(pam_u2f): util.c:422 (get_authenticators): Working with 1 authenticator(s) debug(pam_u2f): util.c:426 (get_authenticators): Checking whether key exists in authenticator 0 debug(pam_u2f): util.c:436 (get_authenticators): Authenticator path: /dev/hidraw5 fido_tx: d=0x55d9300def90, cmd=0x06, buf=0x55d9300def90, count=8 0000: 5c ee 5a f3 48 80 31 6f fido_rx: d=0x55d9300def90, cmd=0x06, buf=0x55d9300def98, count=17, ms=-1 rx_preamble: initiation frame at 0x7ffdb0088320 0000: ff ff ff ff 86 00 11 5c ee 5a f3 48 80 31 6f 00 0016: 00 15 a7 02 01 01 00 01 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rx: payload_len=17 fido_rx: buf=0x55d9300def98, len=17 0000: 5c ee 5a f3 48 80 31 6f 00 00 15 a7 02 01 01 00 0016: 01 fido_tx: d=0x55d9300def90, cmd=0x03, buf=0x55d93012a4c2, count=138 0000: 00 02 07 00 00 00 81 ff ff ff ff ff ff ff ff ff 0016: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 0032: ff ff ff ff ff ff ff 5d f2 32 16 91 05 6d f9 eb 0048: b4 77 25 f9 36 c7 23 ef ab 3c 7f c2 1d 5b 74 fd 0064: 2a b7 75 08 43 4a a4 40 ad d9 ab 5d 99 c8 bb fa 0080: 2a 09 62 4b 41 79 82 ac 10 1f fd ad e3 ee bb d4 0096: e9 0a 0f 40 18 0e 4a 7f 5c 13 14 b2 4c cc 4a ae 0112: bc 00 1a fb 00 d1 b4 75 7f 83 03 eb c3 78 ba 02 0128: 93 73 cc 92 58 67 f5 24 00 00 fido_rx: d=0x55d9300def90, cmd=0x03, buf=0x7ffdb0087d50, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffdb0087c60 0000: 00 00 15 a7 83 00 02 69 85 00 00 00 00 00 00 00 0016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rx: payload_len=2 fido_rx: buf=0x7ffdb0087d50, len=2 0000: 69 85 u2f_authenticate_single: checking for key existence only debug(pam_u2f): util.c:463 (get_authenticators): Found key in authenticator 0 fido_tx: d=0x55d9300def90, cmd=0x03, buf=0x55d93012feb2, count=138 0000: 00 02 07 00 00 00 81 ff ff ff ff ff ff ff ff ff 0016: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 0032: ff ff ff ff ff ff ff 5d f2 32 16 91 05 6d f9 eb 0048: b4 77 25 f9 36 c7 23 ef ab 3c 7f c2 1d 5b 74 fd 0064: 2a b7 75 08 43 4a a4 40 ad d9 ab 5d 99 c8 bb fa 0080: 2a 09 62 4b 41 79 82 ac 10 1f fd ad e3 ee bb d4 0096: e9 0a 0f 40 18 0e 4a 7f 5c 13 14 b2 4c cc 4a ae 0112: bc 00 1a fb 00 d1 b4 75 7f 83 03 eb c3 78 ba 02 0128: 93 73 cc 92 58 67 f5 24 00 00 fido_rx: d=0x55d9300def90, cmd=0x03, buf=0x7ffdb0087d50, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffdb0087c60 0000: 00 00 15 a7 83 00 02 69 85 00 00 00 00 00 00 00 0016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rx: payload_len=2 fido_rx: buf=0x7ffdb0087d50, len=2 0000: 69 85 u2f_authenticate_single: checking for key existence only get_key_val: key_len=4 debug(pam_u2f): pam-u2f.c:418 (pam_sm_authenticate): do_authentication returned -2 debug(pam_u2f): pam-u2f.c:457 (pam_sm_authenticate): done. [Authentication failure] Verification code: hello world ```

Hopefully this helps.

Neither, the idea is that it's possible to set that flag either at the system level (userpresence=1) or at the credential level (+presence), and that the more "restrictive" setting will take effect. However, that logic is a bit tricky because the currently released version of pam-u2f doesn't have the +presence flag but assumes that behavior. On top of that, not setting a flag is not exactly equivalent to setting it to off, but rather it's equivalent to setting it to its default behavior in the specifications.

Thanks for clearing it up! I was getting that impression from reading the source, but I just wanted to confirm; I added userpresence=1 to the relevant line in /etc/pam.d/sudo.

Edit: I noticed I left an incomplete sentence.

a-dma commented 4 years ago

Yes, that was helpful. Thanks.

So, what kind of device do you have? Am I correct in thinking that you have a relatively old device that only does U2F (like a YubiKey NEO or a YubiKey 4) and not a FIDO2-capable one?

Silent authentications (i.e., without testing for user presence) are a relatively new addition to U2F and are supported in FIDO2. Older devices don't implement that version of the specifications, plus libfido2 doesn't implement that behavior over U2F either.

If that's the case I'm afraid there isn't much more I can do to help you with this.

rolandog commented 4 years ago

Wow. You're right, and sorry about that --- it didn't occur to me that that may be a factor.

I tested with a more recent Yubico Security Key, and now I was able to achieve the desired behaviour:

Partially redacted logs from succesful attempt ``` user@computer:~$ sudo echo "hello world" [sudo] password for user: debug(pam_u2f): pam-u2f.c:109 (parse_cfg): called. debug(pam_u2f): pam-u2f.c:110 (parse_cfg): flags 32768 argc 5 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[0]=interactive debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[1]=userpresence=0 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[2]=nouserok debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[3]=authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[4]=debug debug(pam_u2f): pam-u2f.c:114 (parse_cfg): max_devices=0 debug(pam_u2f): pam-u2f.c:115 (parse_cfg): debug=1 debug(pam_u2f): pam-u2f.c:116 (parse_cfg): interactive=1 debug(pam_u2f): pam-u2f.c:117 (parse_cfg): cue=0 debug(pam_u2f): pam-u2f.c:118 (parse_cfg): nodetect=0 debug(pam_u2f): pam-u2f.c:119 (parse_cfg): userpresence=0 debug(pam_u2f): pam-u2f.c:120 (parse_cfg): userverification=-1 debug(pam_u2f): pam-u2f.c:121 (parse_cfg): pinverification=-1 debug(pam_u2f): pam-u2f.c:122 (parse_cfg): manual=0 debug(pam_u2f): pam-u2f.c:123 (parse_cfg): nouserok=1 debug(pam_u2f): pam-u2f.c:124 (parse_cfg): openasuser=0 debug(pam_u2f): pam-u2f.c:125 (parse_cfg): alwaysok=0 debug(pam_u2f): pam-u2f.c:126 (parse_cfg): authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:128 (parse_cfg): authpending_file=(null) debug(pam_u2f): pam-u2f.c:130 (parse_cfg): origin=(null) debug(pam_u2f): pam-u2f.c:131 (parse_cfg): appid=(null) debug(pam_u2f): pam-u2f.c:132 (parse_cfg): prompt=(null) debug(pam_u2f): pam-u2f.c:185 (pam_sm_authenticate): Origin not specified, using "pam://computer" debug(pam_u2f): pam-u2f.c:196 (pam_sm_authenticate): Appid not specified, using the same value of origin (pam://computer) debug(pam_u2f): pam-u2f.c:208 (pam_sm_authenticate): Maximum devices number not set. Using default (24) debug(pam_u2f): pam-u2f.c:226 (pam_sm_authenticate): Requesting authentication for user user debug(pam_u2f): pam-u2f.c:237 (pam_sm_authenticate): Found user user debug(pam_u2f): pam-u2f.c:238 (pam_sm_authenticate): Home directory for user is /home/user debug(pam_u2f): pam-u2f.c:309 (pam_sm_authenticate): Using authentication file /etc/Yubico/u2f_keys debug(pam_u2f): util.c:215 (get_devices_from_authfile): Authorization line: user:KeyHandle1,UserKey1,es256, debug(pam_u2f): util.c:220 (get_devices_from_authfile): Matched user: user debug(pam_u2f): util.c:256 (get_devices_from_authfile): KeyHandle for device number 1: KeyHandle1 debug(pam_u2f): util.c:279 (get_devices_from_authfile): publicKey for device number 1: UserKey1 debug(pam_u2f): util.c:303 (get_devices_from_authfile): COSE type for device number 1: es256 debug(pam_u2f): util.c:318 (get_devices_from_authfile): Unable to retrieve attributes 1 debug(pam_u2f): util.c:319 (get_devices_from_authfile): Assuming 'p' (backwards compatibility) debug(pam_u2f): util.c:354 (get_devices_from_authfile): Found 1 device(s) for user user debug(pam_u2f): pam-u2f.c:382 (pam_sm_authenticate): Using file '/var/run/user/1000/pam-u2f-authpending' for emitting touch request notifications Insert your U2F device, then press ENTER. get_key_val: key_len=4 debug(pam_u2f): util.c:527 (do_authentication): Device max index is 1 debug(pam_u2f): util.c:559 (do_authentication): Attempting authentication with device number 1 debug(pam_u2f): util.c:581 (do_authentication): Key handle: KeyHandle1 debug(pam_u2f): util.c:687 (do_authentication): Challenge: ZbQBSnTF7WQebn4cBfjRtt2A8YayQs0tbEXaJ4wAOkM= debug(pam_u2f): util.c:422 (get_authenticators): Working with 1 authenticator(s) debug(pam_u2f): util.c:426 (get_authenticators): Checking whether key exists in authenticator 0 debug(pam_u2f): util.c:436 (get_authenticators): Authenticator path: /dev/hidraw1 fido_tx: d=0x5633ad7a7660, cmd=0x06, buf=0x5633ad7a7660, count=8 0000: e9 2c d7 63 bf 93 72 54 fido_rx: d=0x5633ad7a7660, cmd=0x06, buf=0x5633ad7a7668, count=17, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffb3b0 0000: ff ff ff ff 86 00 11 e9 2c d7 63 bf 93 72 54 00 0016: 14 00 03 02 05 00 02 05 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rx: payload_len=17 fido_rx: buf=0x5633ad7a7668, len=17 0000: e9 2c d7 63 bf 93 72 54 00 14 00 03 02 05 00 02 0016: 05 fido_dev_get_cbor_info_tx: dev=0x5633ad7a7660 fido_tx: d=0x5633ad7a7660, cmd=0x10, buf=0x7ffc6dffb417, count=1 0000: 04 fido_dev_get_cbor_info_rx: dev=0x5633ad7a7660, ci=0x5633ad7a76d0, ms=-1 fido_rx: d=0x5633ad7a7660, cmd=0x10, buf=0x7ffc6dffaf20, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffae90 0000: 00 14 00 03 90 00 56 00 a6 01 82 66 55 32 46 5f 0016: 56 32 68 46 49 44 4f 5f 32 5f 30 02 81 6b 68 6d 0032: 61 63 2d 73 65 63 72 65 74 03 50 f8 a0 11 f3 8c 0048: 0a 4d 15 80 06 17 11 1f 9e dc 7d 04 a4 62 72 6b rx: payload_len=86 rx: continuation frame at 0x7ffc6dffae90 0000: 00 14 00 03 00 f5 62 75 70 f5 64 70 6c 61 74 f4 0016: 69 63 6c 69 65 6e 74 50 69 6e f4 05 19 04 b0 06 0032: 81 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x7ffc6dffaf20, len=86 0000: 00 a6 01 82 66 55 32 46 5f 56 32 68 46 49 44 4f 0016: 5f 32 5f 30 02 81 6b 68 6d 61 63 2d 73 65 63 72 0032: 65 74 03 50 f8 a0 11 f3 8c 0a 4d 15 80 06 17 11 0048: 1f 9e dc 7d 04 a4 62 72 6b f5 62 75 70 f5 64 70 0064: 6c 61 74 f4 69 63 6c 69 65 6e 74 50 69 6e f4 05 0080: 19 04 b0 06 81 01 fido_dev_open_rx: FIDO_MAXMSG=1200, maxmsgsiz=1200 fido_tx: d=0x5633ad7a7660, cmd=0x10, buf=0x5633ad7a5420, count=168 0000: 02 a4 01 78 22 70 61 6d 3a 2f 2f 72 6f 6c 61 6e 0016: 64 6f 67 2d 49 6e 73 70 69 72 6f 6e 2d 35 35 35 0032: 39 2d 75 32 30 31 39 02 58 20 65 b4 01 4a 74 c5 0048: ed 64 1e 6e 7e 1c 05 f8 d1 b6 dd 80 f1 86 b2 42 0064: cd 2d 6c 45 da 27 8c 00 3a 43 03 81 a2 62 69 64 0080: 58 40 b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e 0096: a6 82 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 0112: fc b5 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c 0128: fe d6 ba 32 cf 18 90 ba 71 ea 7c 64 19 b2 cb b6 0144: a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 0160: 65 79 05 a1 62 75 70 f4 fido_rx: d=0x5633ad7a7660, cmd=0x10, buf=0x7ffc6dffaeb0, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffae20 0000: 00 14 00 03 90 00 ca 00 a3 01 a2 62 69 64 58 40 0016: b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e a6 82 0032: 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 fc b5 0048: 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c fe d6 rx: payload_len=202 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 03 00 ba 32 cf 18 90 ba 71 ea 7c 64 19 0016: b2 cb b6 a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 0032: 63 2d 6b 65 79 02 58 25 5d f2 32 16 91 05 6d f9 0048: eb b4 77 25 f9 36 c7 23 ef ab 3c 7f c2 1d 5b 74 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 03 01 fd 2a b7 75 08 43 4a a4 00 00 00 0016: 00 24 03 58 46 30 44 02 20 1a 69 89 8a 6c af 33 0032: 20 cd 89 10 2b 49 0c ed be 09 1f 32 f9 a4 a1 0a 0048: 72 9d b3 51 2d 50 79 e3 30 02 20 37 42 35 b9 c6 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 03 02 a1 86 81 38 c7 a8 de 47 c0 f3 e3 0016: b2 1a bf 22 49 b7 d6 6d b6 20 01 b8 63 bf f1 a6 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x7ffc6dffaeb0, len=202 0000: 00 a3 01 a2 62 69 64 58 40 b0 14 5d d6 8c a3 2b 0016: 38 57 21 c6 d8 2f 6e a6 82 6c e5 c2 76 d5 67 cf 0032: 0c 35 aa d8 aa 69 63 fc b5 29 42 fd 7b 7d cb cc 0048: 33 d1 65 c8 df 3a 1c fe d6 ba 32 cf 18 90 ba 71 0064: ea 7c 64 19 b2 cb b6 a4 eb 64 74 79 70 65 6a 70 0080: 75 62 6c 69 63 2d 6b 65 79 02 58 25 5d f2 32 16 0096: 91 05 6d f9 eb b4 77 25 f9 36 c7 23 ef ab 3c 7f 0112: c2 1d 5b 74 fd 2a b7 75 08 43 4a a4 00 00 00 00 0128: 24 03 58 46 30 44 02 20 1a 69 89 8a 6c af 33 20 0144: cd 89 10 2b 49 0c ed be 09 1f 32 f9 a4 a1 0a 72 0160: 9d b3 51 2d 50 79 e3 30 02 20 37 42 35 b9 c6 a1 0176: 86 81 38 c7 a8 de 47 c0 f3 e3 b2 1a bf 22 49 b7 0192: d6 6d b6 20 01 b8 63 bf f1 a6 adjust_assert_count: cbor_type adjust_assert_count: cbor_type adjust_assert_count: cbor_type cbor_decode_assert_authdata: buf=0x5633ad7a5510, len=37 debug(pam_u2f): util.c:463 (get_authenticators): Found key in authenticator 0 fido_tx: d=0x5633ad7a7660, cmd=0x10, buf=0x5633ad7a5420, count=168 0000: 02 a4 01 78 22 70 61 6d 3a 2f 2f 72 6f 6c 61 6e 0016: 64 6f 67 2d 49 6e 73 70 69 72 6f 6e 2d 35 35 35 0032: 39 2d 75 32 30 31 39 02 58 20 2d 0b 83 1b 38 77 0048: f8 30 48 d3 a5 a9 1d ad 72 3e 2a 5c de e2 de 55 0064: 2a 0b 1b c3 aa 63 bc 9f 9a dc 03 81 a2 62 69 64 0080: 58 40 b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e 0096: a6 82 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 0112: fc b5 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c 0128: fe d6 ba 32 cf 18 90 ba 71 ea 7c 64 19 b2 cb b6 0144: a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 0160: 65 79 05 a1 62 75 70 f4 fido_rx: d=0x5633ad7a7660, cmd=0x10, buf=0x7ffc6dffaeb0, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffae20 0000: 00 14 00 03 90 00 cb 00 a3 01 a2 62 69 64 58 40 0016: b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e a6 82 0032: 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 fc b5 0048: 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c fe d6 rx: payload_len=203 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 03 00 ba 32 cf 18 90 ba 71 ea 7c 64 19 0016: b2 cb b6 a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 0032: 63 2d 6b 65 79 02 58 25 5d f2 32 16 91 05 6d f9 0048: eb b4 77 25 f9 36 c7 23 ef ab 3c 7f c2 1d 5b 74 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 03 01 fd 2a b7 75 08 43 4a a4 00 00 00 0016: 00 25 03 58 47 30 45 02 20 1e a5 ea f7 60 b2 68 0032: 6c e8 61 07 07 a5 2a 6d 55 e9 bb ed 9c a7 fb 63 0048: 96 62 87 95 b5 ca 67 8a d7 02 21 00 9d c4 55 00 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 03 02 55 e6 b2 0b 92 c1 d6 70 89 21 70 0016: 2f 44 7e a2 7c ca f2 5a e9 d4 48 33 51 e9 b7 cb 0032: 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x7ffc6dffaeb0, len=203 0000: 00 a3 01 a2 62 69 64 58 40 b0 14 5d d6 8c a3 2b 0016: 38 57 21 c6 d8 2f 6e a6 82 6c e5 c2 76 d5 67 cf 0032: 0c 35 aa d8 aa 69 63 fc b5 29 42 fd 7b 7d cb cc 0048: 33 d1 65 c8 df 3a 1c fe d6 ba 32 cf 18 90 ba 71 0064: ea 7c 64 19 b2 cb b6 a4 eb 64 74 79 70 65 6a 70 0080: 75 62 6c 69 63 2d 6b 65 79 02 58 25 5d f2 32 16 0096: 91 05 6d f9 eb b4 77 25 f9 36 c7 23 ef ab 3c 7f 0112: c2 1d 5b 74 fd 2a b7 75 08 43 4a a4 00 00 00 00 0128: 25 03 58 47 30 45 02 20 1e a5 ea f7 60 b2 68 6c 0144: e8 61 07 07 a5 2a 6d 55 e9 bb ed 9c a7 fb 63 96 0160: 62 87 95 b5 ca 67 8a d7 02 21 00 9d c4 55 00 55 0176: e6 b2 0b 92 c1 d6 70 89 21 70 2f 44 7e a2 7c ca 0192: f2 5a e9 d4 48 33 51 e9 b7 cb 15 adjust_assert_count: cbor_type adjust_assert_count: cbor_type adjust_assert_count: cbor_type cbor_decode_assert_authdata: buf=0x5633ad7a59b0, len=37 fido_check_flags: flags=00 fido_check_flags: up=1, uv=0 debug(pam_u2f): pam-u2f.c:457 (pam_sm_authenticate): done. [Success] debug(pam_u2f): pam-u2f.c:109 (parse_cfg): called. debug(pam_u2f): pam-u2f.c:110 (parse_cfg): flags 32768 argc 5 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[0]=cue debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[1]=userpresence=1 debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[2]=nouserok debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[3]=authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:112 (parse_cfg): argv[4]=debug debug(pam_u2f): pam-u2f.c:114 (parse_cfg): max_devices=0 debug(pam_u2f): pam-u2f.c:115 (parse_cfg): debug=1 debug(pam_u2f): pam-u2f.c:116 (parse_cfg): interactive=0 debug(pam_u2f): pam-u2f.c:117 (parse_cfg): cue=1 debug(pam_u2f): pam-u2f.c:118 (parse_cfg): nodetect=0 debug(pam_u2f): pam-u2f.c:119 (parse_cfg): userpresence=1 debug(pam_u2f): pam-u2f.c:120 (parse_cfg): userverification=-1 debug(pam_u2f): pam-u2f.c:121 (parse_cfg): pinverification=-1 debug(pam_u2f): pam-u2f.c:122 (parse_cfg): manual=0 debug(pam_u2f): pam-u2f.c:123 (parse_cfg): nouserok=1 debug(pam_u2f): pam-u2f.c:124 (parse_cfg): openasuser=0 debug(pam_u2f): pam-u2f.c:125 (parse_cfg): alwaysok=0 debug(pam_u2f): pam-u2f.c:126 (parse_cfg): authfile=/etc/Yubico/u2f_keys debug(pam_u2f): pam-u2f.c:128 (parse_cfg): authpending_file=(null) debug(pam_u2f): pam-u2f.c:130 (parse_cfg): origin=(null) debug(pam_u2f): pam-u2f.c:131 (parse_cfg): appid=(null) debug(pam_u2f): pam-u2f.c:132 (parse_cfg): prompt=(null) debug(pam_u2f): pam-u2f.c:185 (pam_sm_authenticate): Origin not specified, using "pam://computer" debug(pam_u2f): pam-u2f.c:196 (pam_sm_authenticate): Appid not specified, using the same value of origin (pam://computer) debug(pam_u2f): pam-u2f.c:208 (pam_sm_authenticate): Maximum devices number not set. Using default (24) debug(pam_u2f): pam-u2f.c:226 (pam_sm_authenticate): Requesting authentication for user user debug(pam_u2f): pam-u2f.c:237 (pam_sm_authenticate): Found user user debug(pam_u2f): pam-u2f.c:238 (pam_sm_authenticate): Home directory for user is /home/user debug(pam_u2f): pam-u2f.c:309 (pam_sm_authenticate): Using authentication file /etc/Yubico/u2f_keys debug(pam_u2f): util.c:215 (get_devices_from_authfile): Authorization line: user:KeyHandle1,UserKey1,es256, debug(pam_u2f): util.c:220 (get_devices_from_authfile): Matched user: user debug(pam_u2f): util.c:256 (get_devices_from_authfile): KeyHandle for device number 1: KeyHandle1 debug(pam_u2f): util.c:279 (get_devices_from_authfile): publicKey for device number 1: UserKey1 debug(pam_u2f): util.c:303 (get_devices_from_authfile): COSE type for device number 1: es256 debug(pam_u2f): util.c:318 (get_devices_from_authfile): Unable to retrieve attributes 1 debug(pam_u2f): util.c:319 (get_devices_from_authfile): Assuming 'p' (backwards compatibility) debug(pam_u2f): util.c:354 (get_devices_from_authfile): Found 1 device(s) for user user debug(pam_u2f): pam-u2f.c:382 (pam_sm_authenticate): Using file '/var/run/user/1000/pam-u2f-authpending' for emitting touch request notifications get_key_val: key_len=4 debug(pam_u2f): util.c:527 (do_authentication): Device max index is 1 debug(pam_u2f): util.c:559 (do_authentication): Attempting authentication with device number 1 debug(pam_u2f): util.c:581 (do_authentication): Key handle: KeyHandle1 debug(pam_u2f): util.c:687 (do_authentication): Challenge: MztLeKSvSGJUUPRdl5QM3CfbFqi1ryq9X5Z6ypC+sCM= debug(pam_u2f): util.c:422 (get_authenticators): Working with 1 authenticator(s) debug(pam_u2f): util.c:426 (get_authenticators): Checking whether key exists in authenticator 0 debug(pam_u2f): util.c:436 (get_authenticators): Authenticator path: /dev/hidraw1 fido_tx: d=0x5633ad7a7870, cmd=0x06, buf=0x5633ad7a7870, count=8 0000: 5c ff 37 21 be 81 f9 1e fido_rx: d=0x5633ad7a7870, cmd=0x06, buf=0x5633ad7a7878, count=17, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffb3b0 0000: ff ff ff ff 86 00 11 5c ff 37 21 be 81 f9 1e 00 0016: 14 00 04 02 05 00 02 05 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rx: payload_len=17 fido_rx: buf=0x5633ad7a7878, len=17 0000: 5c ff 37 21 be 81 f9 1e 00 14 00 04 02 05 00 02 0016: 05 fido_dev_get_cbor_info_tx: dev=0x5633ad7a7870 fido_tx: d=0x5633ad7a7870, cmd=0x10, buf=0x7ffc6dffb417, count=1 0000: 04 fido_dev_get_cbor_info_rx: dev=0x5633ad7a7870, ci=0x5633ad7aa670, ms=-1 fido_rx: d=0x5633ad7a7870, cmd=0x10, buf=0x7ffc6dffaf20, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffae90 0000: 00 14 00 04 90 00 56 00 a6 01 82 66 55 32 46 5f 0016: 56 32 68 46 49 44 4f 5f 32 5f 30 02 81 6b 68 6d 0032: 61 63 2d 73 65 63 72 65 74 03 50 f8 a0 11 f3 8c 0048: 0a 4d 15 80 06 17 11 1f 9e dc 7d 04 a4 62 72 6b rx: payload_len=86 rx: continuation frame at 0x7ffc6dffae90 0000: 00 14 00 04 00 f5 62 75 70 f5 64 70 6c 61 74 f4 0016: 69 63 6c 69 65 6e 74 50 69 6e f4 05 19 04 b0 06 0032: 81 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x7ffc6dffaf20, len=86 0000: 00 a6 01 82 66 55 32 46 5f 56 32 68 46 49 44 4f 0016: 5f 32 5f 30 02 81 6b 68 6d 61 63 2d 73 65 63 72 0032: 65 74 03 50 f8 a0 11 f3 8c 0a 4d 15 80 06 17 11 0048: 1f 9e dc 7d 04 a4 62 72 6b f5 62 75 70 f5 64 70 0064: 6c 61 74 f4 69 63 6c 69 65 6e 74 50 69 6e f4 05 0080: 19 04 b0 06 81 01 fido_dev_open_rx: FIDO_MAXMSG=1200, maxmsgsiz=1200 fido_tx: d=0x5633ad7a7870, cmd=0x10, buf=0x5633ad7a65b0, count=168 0000: 02 a4 01 78 22 70 61 6d 3a 2f 2f 72 6f 6c 61 6e 0016: 64 6f 67 2d 49 6e 73 70 69 72 6f 6e 2d 35 35 35 0032: 39 2d 75 32 30 31 39 02 58 20 33 3b 4b 78 a4 af 0048: 48 62 54 50 f4 5d 97 94 0c dc 27 db 16 a8 b5 af 0064: 2a bd 5f 96 7a ca 90 be b0 23 03 81 a2 62 69 64 0080: 58 40 b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e 0096: a6 82 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 0112: fc b5 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c 0128: fe d6 ba 32 cf 18 90 ba 71 ea 7c 64 19 b2 cb b6 0144: a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 0160: 65 79 05 a1 62 75 70 f4 fido_rx: d=0x5633ad7a7870, cmd=0x10, buf=0x7ffc6dffaeb0, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffae20 0000: 00 14 00 04 90 00 cb 00 a3 01 a2 62 69 64 58 40 0016: b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e a6 82 0032: 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 fc b5 0048: 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c fe d6 rx: payload_len=203 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 04 00 ba 32 cf 18 90 ba 71 ea 7c 64 19 0016: b2 cb b6 a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 0032: 63 2d 6b 65 79 02 58 25 5d f2 32 16 91 05 6d f9 0048: eb b4 77 25 f9 36 c7 23 ef ab 3c 7f c2 1d 5b 74 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 04 01 fd 2a b7 75 08 43 4a a4 00 00 00 0016: 00 26 03 58 47 30 45 02 21 00 f4 1b 01 5d 11 bb 0032: 0c 95 10 c4 39 18 3b a7 5a 95 39 8f 38 fd 3a 16 0048: 3c 3a 1a 4c 83 bc 2a 96 04 46 02 20 4e 4b 6b eb rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 04 02 f1 a8 c5 76 c2 e5 b0 95 37 c0 30 0016: a4 ca 4d 81 6f d0 f7 91 a1 ed 40 96 3d b2 94 09 0032: 71 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x7ffc6dffaeb0, len=203 0000: 00 a3 01 a2 62 69 64 58 40 b0 14 5d d6 8c a3 2b 0016: 38 57 21 c6 d8 2f 6e a6 82 6c e5 c2 76 d5 67 cf 0032: 0c 35 aa d8 aa 69 63 fc b5 29 42 fd 7b 7d cb cc 0048: 33 d1 65 c8 df 3a 1c fe d6 ba 32 cf 18 90 ba 71 0064: ea 7c 64 19 b2 cb b6 a4 eb 64 74 79 70 65 6a 70 0080: 75 62 6c 69 63 2d 6b 65 79 02 58 25 5d f2 32 16 0096: 91 05 6d f9 eb b4 77 25 f9 36 c7 23 ef ab 3c 7f 0112: c2 1d 5b 74 fd 2a b7 75 08 43 4a a4 00 00 00 00 0128: 26 03 58 47 30 45 02 21 00 f4 1b 01 5d 11 bb 0c 0144: 95 10 c4 39 18 3b a7 5a 95 39 8f 38 fd 3a 16 3c 0160: 3a 1a 4c 83 bc 2a 96 04 46 02 20 4e 4b 6b eb f1 0176: a8 c5 76 c2 e5 b0 95 37 c0 30 a4 ca 4d 81 6f d0 0192: f7 91 a1 ed 40 96 3d b2 94 09 71 adjust_assert_count: cbor_type adjust_assert_count: cbor_type adjust_assert_count: cbor_type cbor_decode_assert_authdata: buf=0x5633ad7a7d10, len=37 debug(pam_u2f): util.c:463 (get_authenticators): Found key in authenticator 0 Please touch the device. fido_tx: d=0x5633ad7a7870, cmd=0x10, buf=0x5633ad7a7bc0, count=168 0000: 02 a4 01 78 22 70 61 6d 3a 2f 2f 72 6f 6c 61 6e 0016: 64 6f 67 2d 49 6e 73 70 69 72 6f 6e 2d 35 35 35 0032: 39 2d 75 32 30 31 39 02 58 20 bf f2 7c f6 61 8e 0048: 8d 81 c8 f6 b6 95 25 7f 4a 89 39 0b 26 bf b9 ea 0064: 64 87 7e 3d 2c 1a b8 72 5c b1 03 81 a2 62 69 64 0080: 58 40 b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e 0096: a6 82 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 0112: fc b5 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c 0128: fe d6 ba 32 cf 18 90 ba 71 ea 7c 64 19 b2 cb b6 0144: a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 0160: 65 79 05 a1 62 75 70 f5 fido_rx: d=0x5633ad7a7870, cmd=0x10, buf=0x7ffc6dffaeb0, count=1200, ms=-1 rx_preamble: initiation frame at 0x7ffc6dffae20 0000: 00 14 00 04 90 00 cb 00 a3 01 a2 62 69 64 58 40 0016: b0 14 5d d6 8c a3 2b 38 57 21 c6 d8 2f 6e a6 82 0032: 6c e5 c2 76 d5 67 cf 0c 35 aa d8 aa 69 63 fc b5 0048: 29 42 fd 7b 7d cb cc 33 d1 65 c8 df 3a 1c fe d6 rx: payload_len=203 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 04 00 ba 32 cf 18 90 ba 71 ea 7c 64 19 0016: b2 cb b6 a4 eb 64 74 79 70 65 6a 70 75 62 6c 69 0032: 63 2d 6b 65 79 02 58 25 5d f2 32 16 91 05 6d f9 0048: eb b4 77 25 f9 36 c7 23 ef ab 3c 7f c2 1d 5b 74 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 04 01 fd 2a b7 75 08 43 4a a4 01 00 00 0016: 00 27 03 58 47 30 45 02 21 00 d7 8b 58 ee a4 d3 0032: 48 f4 a9 fc d5 1a 81 85 79 d2 a1 cf f1 bd fd 52 0048: 29 05 bf a4 6c 90 e4 6b cf cf 02 20 73 6e 82 75 rx: continuation frame at 0x7ffc6dffae20 0000: 00 14 00 04 02 78 ae 43 ef f7 c4 64 85 65 f9 6e 0016: ad e4 5a b4 28 13 da 4b 7a b3 cc 28 9c bc 7e 77 0032: e7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x7ffc6dffaeb0, len=203 0000: 00 a3 01 a2 62 69 64 58 40 b0 14 5d d6 8c a3 2b 0016: 38 57 21 c6 d8 2f 6e a6 82 6c e5 c2 76 d5 67 cf 0032: 0c 35 aa d8 aa 69 63 fc b5 29 42 fd 7b 7d cb cc 0048: 33 d1 65 c8 df 3a 1c fe d6 ba 32 cf 18 90 ba 71 0064: ea 7c 64 19 b2 cb b6 a4 eb 64 74 79 70 65 6a 70 0080: 75 62 6c 69 63 2d 6b 65 79 02 58 25 5d f2 32 16 0096: 91 05 6d f9 eb b4 77 25 f9 36 c7 23 ef ab 3c 7f 0112: c2 1d 5b 74 fd 2a b7 75 08 43 4a a4 01 00 00 00 0128: 27 03 58 47 30 45 02 21 00 d7 8b 58 ee a4 d3 48 0144: f4 a9 fc d5 1a 81 85 79 d2 a1 cf f1 bd fd 52 29 0160: 05 bf a4 6c 90 e4 6b cf cf 02 20 73 6e 82 75 78 0176: ae 43 ef f7 c4 64 85 65 f9 6e ad e4 5a b4 28 13 0192: da 4b 7a b3 cc 28 9c bc 7e 77 e7 adjust_assert_count: cbor_type adjust_assert_count: cbor_type adjust_assert_count: cbor_type cbor_decode_assert_authdata: buf=0x5633ad7aa9a0, len=37 fido_check_flags: flags=01 fido_check_flags: up=2, uv=0 debug(pam_u2f): pam-u2f.c:457 (pam_sm_authenticate): done. [Success] hello world ```

I'll close this issue, as this would accomplish what I was looking for.

Should I file a new issue to keep track of the Attribute-parsing issue for multiple keys?

a-dma commented 4 years ago

Ah, good. Glad that the mystery has been solved and that you have a more recent device that solves your use-case.

I am already aware of the issue with the attribute parsing and I was working on a fix for it in the SSH format branch, I just seem to never have time to dedicate to this project. It should be just a quick fix. I'll try to get it out "soon".

Thanks again for patiently testing.

rolandog commented 4 years ago

Not a problem! And thank you for patiently helping me debug the issue.

Although perhaps in retrospect, it would be nice to know which options in pam-u2f require a FIDO2-capable U2F device, and which are backwards-compatible, for future sysadmins. This would bring the pending documentation tasks to:

I'm not sure if they'll be merged on the SSH branch, or on master; if you'd like, I can submit a pull request.

In the meantime, I'll keep an eye on the SSH branch, and order a new Yubikey (because I like to have a spare device in case I lose one).

a-dma commented 4 years ago

Indeed, those are all valid points. The README file still reflects the old/current version of the project, that's why the dependencies are incorrect.

A bit pedantic maybe, but the idea is that FIDO2 is backwards compatible with U2F, the actual issue is that the version of U2F required is 1.2, which only YubiKeys that already support FIDO2 implement.

Let me try to fix the parsing issue in the SSH branch and get that merged in in a relatively short amount of time. It'll then be easier to contribute to the right place and hopefully get a new release out at some point.

As a side note, the fact that you had to replace your authfile when switching to the git version of this project worries me, as it would be a problem for anybody who is updating. I hope that was due to lots of different things all moving at the same time (there is a test to parse both new and old formats and it passes).

rolandog commented 4 years ago

A bit pedantic maybe, but the idea is that FIDO2 is backwards compatible with U2F, the actual issue is that the version of U2F required is 1.2, which only YubiKeys that already support FIDO2 implement.

You're technically correct; the best kind of correct! :laughing:

Let me try to fix the parsing issue in the SSH branch and get that merged in in a relatively short amount of time. It'll then be easier to contribute to the right place and hopefully get a new release out at some point.

I'll be on standby if anything needs to be tested, or to contribute in some small way.

As a side note, the fact that you had to replace your authfile when switching to the git version of this project worries me, as it would be a problem for anybody who is updating. I hope that was due to lots of different things all moving at the same time (there is a test to parse both new and old formats and it passes).

I'll try to replicate soon by creating an authfile with the 1.0.8 version, then upgrading everything to master and test with my FIDO2-capable security key. It may very well have been an issue on my end (or due to the fact that the authfile had two keys listed, and I was using the one that wasn't FIDO2-capable as my first option).

a-dma commented 4 years ago

I have pushed a bit of a reworked logic for parsing authentication files that is hopefully more robust than the previous. I've also added a whole slew of tests checking different combinations of options and number of devices/credentials.

All seems good on my end, but if you're willing to take a look at your convenience it would greatly be appreciated. The latest commit is cbd0ac7b455e1435a683f5a8bc5285b6c1f76423. Thanks!

rolandog commented 4 years ago

Hello. Sorry for the delay!

I ran sudo make uninstall, installed the 1.0.8 version available for Ubuntu, ran pamu2fcfg, and set everything up... and, it worked!

~The one thing I noticed is that, when parsing a previously generated auth_file, setting userpresence=0 worked as if it had been specified in a new configuration file (in other words, previous versions would infer +presence; since it is omitted, it is parsed as if I had ran pamu2fcfg -P).~

I was about to be done, but I wanted to generate a new auth_file, however I ran into the following error when running pamu2fcfg: bash: /usr/bin/pamu2fcfg: No such file or directory.

After running which pamu2fcfg, it reports that it is located in /usr/local/bin/pamu2fcfg.

Edit: I noticed checked out a different commit; I'll test against cbd0ac7.

a-dma commented 4 years ago

Great, thanks for testing!

Old credentials/devices didn't have the concept of not checking for user presence and therefore there was no such option. The intended behavior with +presence is to maintain backwards compatibility, hence it is on by default no matter if it's a new or an old credential.

Similarly, the userpresence=0 option also didn't exist hence it won't be assumed unless somebody specifically turns that on by changing the configuration of the module, in which case it will be honored.

The aim here is to allow a working system to be upgraded without breaking and without resulting in a completely different behavior.

Regarding the location of pamu2cfg, the path that you described is what is used by default if you build and install the package yourself from a git checkout. If you want the binaries to end up in a different place you can use the --prefix option when calling ./configure.

rolandog commented 4 years ago

Hi @a-dma . Thanks for pointing that out; once I used ./configure --prefix=/usr and followed the building instructions, everything worked fine.

It turns out that I had checked out a different commit and, once I tested commit cbd0ac7, everything worked as expected (I updated my previous comment).

I tested with a single key and also with two keys (the second being the older device mentioned above, as my new device has yet to arrive); I also tested userpresence=0 with the older key but, as expected, it doesn't work and falls back to the other authentication method I had set up in the pam rules.

I can confirm, on my end, that pamu2fcfg version 1.0.8 authentication files are compatible with commit pam-u2f from cbd0ac7, and that it also parses attributes from multiple keys.

a-dma commented 4 years ago

Thanks a lot, that's very valuable feedback. Appreciate the effort.

rolandog commented 4 years ago

No problem! Thank you for the effort put on the SSH branch!