pyscripter / Ssh-Pascal

Delphi ssh library wrapping libssh2
MIT License
78 stars 32 forks source link

Bug Authentication SSH-KEY #17

Open marcianobandeira opened 6 days ago

marcianobandeira commented 6 days ago

Hello, congratulations on your project, it's great!

I'm having a problem when using the ssh tunnel to authenticate using an ssh key. When I'm debugging the application, something strange happens, but it works. Please watch the video below: https://www.youtube.com/watch?v=ail18nxIyNY

However, when I'm outside of Delphi, running the application directly, I get an access violation in ntdll.dll.

Below is an image of the code at the exact point where I capture the exception and also an image with the message displayed on my system. Codigo Delphi Erro SSH Key Sem Delphi

Is there any way to use the contents of the ssh-key so that I don't have to save the temporary file on disk?

pyscripter commented 4 days ago

I have noticed in https://libssh2.org/libssh2_userauth_publickey_fromfile_ex.html that: publickey - Path name of the public key file. (e.g. /etc/ssh/hostkey.pub). If libssh2 is built against OpenSSL, this option can be set to NULL.

publickey can only be nil if libssh2 is built against OpenSSL. If you are using the binaries in this repo they are built against Microsoft's WinCNG. So I have modified TSshSession.UserAuthKey to accept a PublicKeyFile parameter as well.

Could you please test with a public key file as well and report whether this fixes the error?

pyscripter commented 4 days ago

@marcianobandeira Could you please provide some feedback on the fix?

marcianobandeira commented 3 days ago

Hello @pyscripter , I have a private key and I generated the public key with the following command: openssl rsa -in private-key.pem -pubout > public-key.pub

After that, with the project source code updated with github, I passed the parameters as follows:

FSession.UserAuthKey(cUser, 'd:\public-key.pub', 'd:\private-key.pem', cPassSshKey);

However, it no longer worked, not even when debugging through Delphi as it did before.

pyscripter commented 3 days ago

As you see below UserAthKey is a thin wrapper to the API function:

function TSshSession.UserAuthKey(const UserName, PublicKeyFile, PrivateKeyFile,
  PassPhrase: string): Boolean;
Var
  M: TMarshaller;
begin
  if FState = session_Authorized then Exit(True);
  if FState <> session_Connected then Exit(False);

  if amKey in AuthMethods(UserName) then
    Result := libssh2_userauth_publickey_fromfile(FAddr,
      M.AsAnsi(UserName, FCodePage).ToPointer,
      M.AsAnsi(PrivateKeyFile, FCodePage).ToPointer,
      M.AsAnsi(PrivateKeyFile, FCodePage).ToPointer,
      M.AsAnsi(PassPhrase, FCodePage).ToPointer) = 0
  else
    Result := False;

  if Result then
  begin
    FState := session_Authorized;
    FUserName := UserName;
  end;
end;

This is how it is used in the libssh2 examples:

static const char *pubkey = "/home/username/.ssh/id_rsa.pub";
static const char *privkey = "/home/username/.ssh/id_rsa";

while((rc = libssh2_userauth_publickey_fromfile(session, username,
                                                        pubkey, privkey,
                                                        password)) ==
              LIBSSH2_ERROR_EAGAIN);
        if(rc) {
            fprintf(stderr, "Authentication by public key failed.\n");
            goto shutdown;
        }
    }

I have modified the code to check for LIBSSH2_ERROR_EAGAIN (would only happen is the session was non-blocking). Can you try again?

What is the return value you are getting? You can use CheckLibSsh2Result to get the error message.

Normally you generate keys using ssh-keygen. It is possible that your key is not accepted by the server. Does ssh -i '/path/to/keyfile' username@server work?

Note: You can still use an empty string as PublicKeyFile, and that would behave the same as it was before PublicKeyFile was introduced.

marcianobandeira commented 2 days ago

Hello @pyscripter

I noticed that the "UserAuthKey" function does not use the PublicKeyFile parameter, see the print below: Function UserAuthKey

However, even changing the function as shown in the image above, I receive a return of -16 and using the CheckLibSsh2Result method I receive the message as below (In the UserName parameter of the UserAuthKey function, I am using the same username that I use to access my server with the private key):

Error Public Key

Regarding my public key generated with ssh-keygen, comparing its content with my server's authorized_keys, it was really different. So I generated it using PuttyGen, this time the content of the public key is identical to my server's authorized_keys.

I can access the server using ssh -i privatekey... I can't using ssh -i publickey.

I also can't get the same behavior as before by passing an empty string in the PublicKeyFile parameter of the UserAuthKey function, even after the adjustment as per the first print.

pyscripter commented 2 days ago

I fixed the error in UserAuthKey.

However when I tried, I could not get it to work either. Not sure what the issue is. I use ssh agent authentication with the same keys and that works fine.

I am not sure whether this is a libssh2 issue or the way this repo uses its functions. When I searched, I found many issues related to libssh2_userauth_publickey_fromfile, but they appear to have been fixed.

I leave the issue open hoping that someone finds a solution.

marcianobandeira commented 21 hours ago

Hello @pyscripter,

Thank you very much for your time. I will try to find a solution here, and if I find a solution I will post it here.