-
Notifications
You must be signed in to change notification settings - Fork 345
Adding PKCS11 support to SSH agent #537
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
Adding PKCS11 support to SSH agent #537
Conversation
@yan4321 Thanks for adding this support. |
@yan4321 - Please provide the instructions to test. It would be great if you can add some unit tests. |
@yan4321 This will be extremely useful |
@bagajjal , I've updated the PR description with instructions on how to test this. |
Also looking forward to this for smartcard based authentications |
Can this be reviewed+merged before we diverge again and are back to square one? :) |
@yan4321 - would you be able to do an (unofficial) GH release on your fork, with the binaries, while this is in progress? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
I was asked by @bagajjal to take a look at this PR and left some comments. A disclaimer: although I have been dipping my toes lately, I am not a Windows guy. Apologies in advance if anything I said comes across as nonsensical.
Thank you,
-p.
@martelletto, Thank you for the review and input - highly appriciated! @kaelanfouwels, Since an unofficial release would involve generating binaries, would it make more sense for the admins of the repo to generate them? It's as simple as recompiling the solution with the only difference being |
@yan4321 Looks good; thank you! I left two further small comments. Please feel free to mark resolved conversations as such (GitHub won't let me, since I am not the PR author nor do I have write permission on the repository). |
@martelletto, Thanks again for reviewing and for the additional comments. I've addressed them and would appreciate it if you could take another look. |
@yan4321 Thank you! I've left a small remark above. |
ssh-pkcs11.h
Outdated
void pkcs11_terminate(void); | ||
int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); | ||
int pkcs11_del_provider(char *); | ||
struct sshkey * lookup_key(const struct sshkey *); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move the windows specific code to #ifdef WINDOWS block. Please add comments why there is a deviation.
@@ -31,6 +31,11 @@ | |||
#include "agent.h" | |||
#include "agent-request.h" | |||
|
|||
#ifdef ENABLE_PKCS11 | |||
#include "ssh-pkcs11.h" | |||
#define ENABLE_PKCS11 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you define ENABLE_PKCS11 in https://github.com/PowerShell/openssh-portable/blob/latestw_all/contrib/win32/openssh/config.h.vs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 36 is hit only when ENABLE_PKCS11 is defined? This is redundant and can be deleted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this is already defined in
#define ENABLE_PKCS11 1 |
@yan4321 - ssh-keygen is crashing while I was trying, |
@bagajjal , The issue you described above has nothing to do with the changes in this PR. I'm also happy to assist with the testing on a side-channel such as email and if we find any issues we can bubble them here. This might work better as it'll keep this PR thread cleaner and more focused on the review process. Either way, happy to help with any issues. |
Thanks for your quick reply. I'm running into issues as "ssh-add -s <path_to_opensc-pkcs11.dll>” asks for passphrase and returns an error “communication with agent failed”. I sent an email to your Gmail. Thanks for your support in testing. |
@bagajjal, was ssh-agent built with @yan4321, two quick observations regarding the gist:
|
@martelletto - Isn't it (ENABLE_PKCS11) already defined in config.h.vs? What additoinal changes are required in ssh-agent?
|
@bagajjal, |
@bagajjal , @martelletto , I think it boils down to the following question:
The end result will be the same. With option number (2), we separate between implementing the support and enabling it by default, which could be considered safer. |
@yan4321 , @martelletto, @yan4321 , please make changes to enable it by default. ssh-add.exe asks for passphrase while trying to add opensc-pkcs11.dll. |
contrib/win32/win32compat/w32fd.c
Outdated
@@ -1071,7 +1071,9 @@ spawn_child_internal(const char* cmd, char *const argv[], HANDLE in, HANDLE out, | |||
if (strstr(cmd, "sshd.exe")) { | |||
flags |= DETACHED_PROCESS; | |||
} | |||
|
|||
if (strstr(cmd, "helper.exe")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please be explicit with the binary names..
change this to
ssh-pkcs11-helper.exe, ssh-sk-helper.exe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
ssh-pkcs11-client.c
Outdated
|
||
if ((user_token = get_current_user_token()) == NULL || | ||
posix_spawnp_as_user((pid_t *)&pid, av[0], &actions, NULL, av, NULL, user_token) != 0) { | ||
error("posix_spawnp_as_user failed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error_f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed. Thanks!
ssh-pkcs11.c
Outdated
@@ -77,6 +77,15 @@ struct pkcs11_key { | |||
int keyid_len; | |||
}; | |||
|
|||
#ifdef WINDOWS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the changes in this file are required as we have a copy of these functions/structs in ssh-pkcs11-client.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, you're right. Removed the unnecessary parts here.
ssh-pkcs11-client.c
Outdated
av[2] = NULL; | ||
HANDLE user_token = NULL; | ||
|
||
if ((user_token = get_current_user_token()) == NULL || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please have a error log if get_current_user_token() fails to return the user token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the latest commit, we no longer use get_current_user_token()
@yan4321 - I had similar code changes (private) except the way the user token is retrieved. I provided my private binaries on friday 2/11. I'm going to take your changes as they are pretty close. Appreciate all your contributions. |
WTSFreeMemory(session_info); | ||
|
||
// Get token of the logged in user by the active session ID | ||
ret = WTSQueryUserToken(session_id, ¤t_token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Major comment.
windows 10, windows 11 allows multiple RDP sessions. https://www.helpwire.app/blog/allow-multiple-remote-desktop-connections-windows-10/
If a customer has multiple RDP sessions then line 432 doesn't guarantee to return the session ID associated with the correct login user? We end up creating the process in different user namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This again leads to security issue.
Let's say two users have active RDP sessions. One of them is non-admin and the other is admin.
Let's say non-admin runs ssh-add with a malicious PKCS11 provider, this function returns the token associated with admin user then he gains the access to the whole SYSTEM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct that get_current_user_token()
assumes there is only single logged-in user. I'll address that shortly. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the latest commit, we use the pid
of the client connecting to ssh-agent
to retrieve the user token, and use that token to start the helper as that user. That way, even if there are multiple logged-on users, the helper will be spawned as the exact user who originated the request.
I've verified with procmon that the helper is spawned as the expected user.
Thanks for bringing up the multi logged-on users scenario!
@bagajjal , Appreciate your review! |
av[2] = NULL; | ||
|
||
if ((client_process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, sshagent_client_pid)) == NULL || | ||
OpenProcessToken(client_process_handle, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &client_token) == FALSE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't use the same token, we should duplicate the token and pass it to line 473.
I will take care of this. I will merge your PR.
Thanks a lot for your contributions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more issue, over SSH to localhost this wouldn't work. Because the SSH session is in session 0, smart card authentication wouldn't work in session 0. I think it's fine because customer is expected to physically present with the smart card and there wouldn't be a need to do over SSH to localhost. .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bagajjal , Can you be a bit more clear about the scenario you are describing, please?
The helper shouldn't run in session 0 since this session has elevated privileges and the whole point here is for the helper to be executed with the same (reduced) privileges as the client (which doesn't run in session 0).
This implementation achieves that and ssh
to localhost works as shown in the screenshot below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the normal behavior. I'm talking about SSH connection made over the SSH.
First you make an SSH connection to the machine (which has smart card). Now over the SSH connection, if you try to run "ssh-add -s " then it will fail because the ssh-add.exe process id is running in session 0.
As I said, this is a corner case as we expect the customer to be physically present with the smart card to use it. When customer is physically present, there is no point why customer should try ssh-add.exe over an SSH connection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bagajjal , What you are describing requires ssh-agent forwarding to be enabled (except, running ssh-add -s
on the jump host doesn't make much sense. Running ssh <target_host>
with the forwarded agent does).
On a Linux-based system, with agent-forwarding enabled the following scenario is supported and would work:
- Client machine initiates ssh connection to the jump host with agent forwarding using a pkcs11 key.
- Jump host (which the smartcard isn't connected to) initiates ssh connection to the target host - since the agent was forwarded from the client machine via a socket- the authentication (sign request) will happen on the client machine, where the smartcard is connected.
This is one of the reasons Yubikeys have the capability to set touch policy on pkcs11 keys - If an authentication attempt was made through a forwarded agent on a remote host (where the Yubikey isn't connected), the user will be made aware of this (the Yubikey will flash) and will have to physically touch the key for the authentication to proceed.
If agent forwarding is implemented for Windows, this should also work. I'll try to test this out soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Windows is missing ssh-agent forwarding. It's there in our backlog. It would be great if you can contribute for the ssh-agent forwarding.
💯Thanks for the effort Yan and bagajjal |
Sorry for late reply. I do have good news though. Adding the keys from our cards with ssh-add -s do work Extracting the public keys with ssh-keygen -D also works as expected. With the card removed it fails as expected. SSH-add -D removes the keys Therefore I would say that all test cases completed successfully |
@bagajjal I have installed V8.9.0.0p1-Beta from https://github.com/PowerShell/Win32-OpenSSH/releases/tag/v8.9.0.0p1-Beta but I am getting an error after entering PIN when trying to add yubikey to ssh-agent using either OpenSC or Yubico PIV: ssh-add -s "C:\Program Files\Yubico\Yubico PIV Tool\bin\libykcs11.dll" ssh-add -s "C:\Program Files\OpenSC Project\OpenSC\pkcs11\opensc-pkcs11.dll" |
@jdewitee - I'm guessing you installed the V8.9 using the MSI. If yes, there is a bug in the MSI. please refer to PowerShell/Win32-OpenSSH#1914. If not, please have a look at event viewer log for the error message. |
@bagajjal Thanks. Yes I was using MSI. Working now with zip version. |
@jdewitee - You can try the MSI of V8.9.1.0 as well. V8.9.1.0 released yesterday. https://github.com/PowerShell/Win32-OpenSSH/releases/tag/v8.9.1.0p1-Beta |
Seeing same issue using MSI or zip for OpenSSH_for_Windows_8.9p1, LibreSSL 3.4.3 |
@meistars Make sure you have the C:\Program Files\Yubico PIV Tool\bin\ path listed in the SYSTEM environment variable for %Path% (not the user environment variable, as ssh-agent runs in a different environment context to your normal user. Check your Event Viewer logs (under Application and Services Logs->OpenSSH->Admin) for detailed error messages. Just wanted to share, as I was initially running into this same issue. Works now. |
I try different solution but I have the same issue as @meistars Path : Copy paste in openssh folder: |
Also just hit PowerShell/Win32-OpenSSH#1548. Was PKCS11 support in the ssh-agent ever confirmed to have worked? |
No, this never worked.(I am not a maintainer on this package)On 13 Jun 2024, at 11:29, minfrin ***@***.***> wrote:
Also just hit PowerShell/Win32-OpenSSH#1548. Was PKCS11 support in the ssh-agent ever confirmed to have worked?
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
I've just tested with the latest release (9.5p1) installed via MSI - pkcs#11 works with a Nitrokey HSM and OpenSC. Make sure the agent service as well as ssh-add and ssh are the new binaries - the agent should be updated automatically, but you'll have the old ssh/ssh-add in the path. |
@meistars, @baimard, @minfrin, @fouwels, @bwachter, I just re-tested this using both 32 and 64-bit binaries of the latest release (v9.5.0.0p1-Beta) and all smartcard functionality seems to be working well. I posted some suggestions for troubleshooting here. |
Currently, PKCS11 keys work when using the SSH client with the -I switch.
However, In the SSH agent, there is no support for adding/removing/signing PKCS11 keys.
This PR aims to add this functionality to the Windows SSH agent.
This PR is based on the original PR - #362. Since the original PR was made a while ago, It'll be challenging to review after a rebase - hence I'm opening this one.
Tested with SoftHSM2 and Yubikey 4. Instructions on how to test can be found here.