Public Key Authentication with C++ Builder 6 - WeOnlyDo Discussion board

Public Key Authentication with C++ Builder 6 (wodSSH / wodSSH.NET)

by David Lucas, Tuesday, July 19, 2005, 12:44 (6859 days ago)

Posting this to the forum in case the answer helps others in the future.

I'm struggling to authenticate with an OpenSSH server (Windows XP) using public key authentication. I can authenticate with the server using Putty, but I receive the error key not found when using wodSSH (I can also authenticate using password authentication - either through Putty or wodSSH). I think the problem may lie in the retrieval of the Private Key - since when its returned as a WideString the first few characters are NULL. If you retrieve it as a SAFEARRAY then an authentication attempt actually takes place, but still fails.


Here is my code:

if(!ClientKey) ClientKey = new TKeys(NULL);

WideString Filename = c:\program files\openssh\etc\TestKey ;
if(FileExists(Filename))
{
ClientKey->Load(Filename);
}
else
{
ClientKey->Generate(Wodsshkeylib_tlb::RSAkey);
ClientKey->Save(Wodsshkeylib_tlb::RSAkey, Filename);
}


if(!Client) Client = new TwodSSHCom(NULL);

Client->set_Protocol(Wodsshcomlib_tlb::SSHAuto);
Client->set_Hostname(WideString( localhost ));

Client->set_Authentication(Wodsshcomlib_tlb::authPubkey);

// Using the get_PrivateKey method simply causes it to hang,
// whereas this will actually 'attempt' to authenticate.
SAFEARRAY *PrivateKey = ClientKey->get_PrivateKeyData
(Wodsshkeylib_tlb::RSAkey);
Client->set_PrivateKey(TVariant(PrivateKey));

Client->set_Port(22);
Client->set_Blocking(true);

Client->set_Login(WideString( lucasd ));
Client->set_Password(WideString( july2005 ));

Client->OnConnected = ClientConnected;
Client->OnReceived = ClientReceived;
Client->OnLoginChallenge = ClientLoginChallenge;

Client->Connect1();

Hoping you can shed some light on what I'm doing wrong,

Regards,


David Lucas
Data Track Technology

Re: Public Key Authentication with C++ Builder 6

by David Lucas, Tuesday, July 19, 2005, 12:55 (6859 days ago) @ David Lucas

*smack head*

I was loading a different key (I messed up the path). This actually works, so if anyone wants an example of using public key authentication with wodSSH under C++ Builder you've got one ;)

Got there in the end. It still doesn't work if you use the get_PrivateKey method though (those NULLS seem screwy... an oddity of C++ Builder perhaps?).


Cheers,

David Lucas
Data Track Technology

Re: Public Key Authentication with C++ Builder 6

by wodSupport, Tuesday, July 19, 2005, 23:35 (6859 days ago) @ David Lucas

David,

one small note. Instead of passing binary data using SafeArray, you can pass reference to wodKeys component to PrivateKey property! So, use also VARIANT, but put LPDISPATCH inside (you would put ClientKey there) and pass it to wodSSH - that should be the best (and cleanest) way.

Re: Public Key Authentication with C++ Builder 6

by David Lucas, Thursday, July 21, 2005, 16:51 (6857 days ago) @ wodSupport

David,

one small note. Instead of passing binary data using SafeArray, you can pass reference to wodKeys component to PrivateKey property! So, use also VARIANT, but put LPDISPATCH inside (you would put ClientKey there) and pass it to wodSSH - that should be the best (and cleanest) way.

Do you have any example code detailing how to do this? My COM knowledge is extremely limited.

I'm having a hard time trying to work out how to load a private key without calling the Load method on TKeys (our Keys will be stored in a database and I'm trying to avoid having to write the keys to file simply to read them in using the Load method).

I assume you can simply set the TKeys::PrivateKey property, but I'm not sure what format it expects the data to be in (i.e. Am I supposed to remove control characters? The -----BEGIN RSA PRIVATE KEY----- tags? Etc).


Regards,

David Lucas
Data Track Technology

Re: Public Key Authentication with C++ Builder 6

by David Lucas, Thursday, July 21, 2005, 17:27 (6857 days ago) @ David Lucas

I just noticed the example in the help and managed to get it working like you suggested with a little C++ Builder massaging:

VARIANT var;
var.vt = VT_DISPATCH;
var.pdispVal = (LPDISPATCH)ClientKey->GetDefaultInterface();

Client->set_PrivateKey(var);

However, I'm still at a loss as to how I can load keys without storing the key in a file and calling the Load method.


Regards,

David Lucas
Data Track Technology

Re: Public Key Authentication with C++ Builder 6

by wodSupport, Thursday, July 21, 2005, 20:37 (6857 days ago) @ David Lucas

David,

I am not sure I understand. You want to keep private key in some other file, or in memory? What would you do after you Load it? Or, if you don't Load it, where would you get it from?

In either case, you would need to use PrivateKey or PrivateKeyData properties, you wouldn't be able to pass instance of wodKeys directly as I suggested.

Re: Public Key Authentication with C++ Builder 6

by David Lucas, Friday, July 22, 2005, 09:45 (6856 days ago) @ wodSupport

What we want to be able to do, is store the private keys in a database (such as Microsoft SQL Server) and load them into the wodKeys component from there (i.e. into a byte/character array or string first, then pass that to wodKeys using the put_PrivateKey method).

However, we have been unable to do this, and I wanted to know if it was possible, or if the only way of loading the keys was to store them in a file first, then load that file with the wodKeys load method.

Hope that clears it up,

David Lucas
Data Track Technology

Re: Public Key Authentication with C++ Builder 6

by wodSupport, Friday, July 22, 2005, 10:18 (6856 days ago) @ David Lucas

I think in newest wodKeys you can specify full ASCII key to Load method. So, you should get key contents (----- BEGIN PRIVATE KEY....) into a string variable, and pass it to Load method. That should work, I think.

Re: Public Key Authentication with C++ Builder 6

by David Lucas, Friday, July 22, 2005, 11:13 (6856 days ago) @ wodSupport

I think in newest wodKeys you can specify full ASCII key to Load method. So, you should get key contents (----- BEGIN PRIVATE KEY....) into a string variable, and pass it to Load method. That should work, I think.

Has that version been released? Because we have what I believe is the latest version of the dll (1.1.2.9) and the source code version of wodSSH. From the source code, it looks like its just attempting to open the file with the specified filename, and bombing out with an error if the fopen fails. Looks like it then calls a function in an SSL library (if the fopen was successful) which expects a file pointer.

So maybe there's no alternative to temporarily storing the key in a file after retrieving it from the database, loading that temporary file then deleting it afterwards.


David Lucas
Data Track Technology

Re: Public Key Authentication with C++ Builder 6

by wodSupport, Friday, July 22, 2005, 11:37 (6856 days ago) @ David Lucas

David,

I checked this code in VB and it works correctly, so you can put full private key as argument to Load method, instead of pointing it to a file: [code]wodKeys.Load -----BEGIN RSA PRIVATE KEY----- & vbCrLf & _
MIICWwIBAAKBgQDGMw364uWetSfhM+7QyxVRWUXcnkg4Y6ffYayck77uKFmh0zEQ & vbCrLf & _
3oz5G0lg2TjGVpwva6BIzrQSlXSCvp4IW80UclqyoK2hbGQGtVLKfeqzymAp7HNF & vbCrLf & _
VQtc7DiDKa0UxWQmsD2389TPFaoFP3sLCV+1ksr6JAbBHClI1zs1WyJx1QIBIwKB & vbCrLf & _
gDL3L3sHJRoulTnoyGGTTp/jwYHfjuntvXP0i3i4RwoKYDDtKd/EMuD4Y1NrDplm & vbCrLf & _
unKYBKUB88pDsD7gjwl2sRNuIOyMmeeBr6tSR3NwD7aT9q5A9LfjS4J1CeccL2pp & vbCrLf & _
zhAv48t3JcBH4Y/IgDFXoJaoeBTN5N/ucjKIv5XDPj1LAkEA/3NsgSWItIgIHXf3 & vbCrLf & _
BG2hpDbn4WTdKss5gVM1Us/vCPiCq9qbYzTWtSzlOi7bi2O98nt77lXgOYu/n7tG & vbCrLf & _
I7jjxQJBAMagH/y/zU2/DwKMEozOL63buNWPnQuotk5pdb6Wh+gRZRFCk4hifmVl & vbCrLf & _
RjJ2GkWn5p9gENwaXZioi85d/iOwZtECQQDpjhoPrUnJoPF6B0g+kB7CBlBZC8Ll & vbCrLf & _
TBdRqylwSRUPhB+zEQMY39o/Pv13BkURukdEGSDZ6B12cSQ6RNJpzZ0LAkARBmkk & vbCrLf & _
SvRXHwFJXHaeWtDjBDRqE5+/K7fa1dbkc016SqJDTtlyFxIl8rzfwPrwBxPEhJO7 & vbCrLf & _
GDPog3mymlecqLhbAkEAu3xh8WNQpHsdmYWZzvaezwMv0cv+MzGzLFnZprBEksdp & vbCrLf & _
RBxrZBrzIVAcCGOvpbUt3Btj3KZKkJvf0zh4utf1hQ== & vbCrLf & _
-----END RSA PRIVATE KEY----- [/code]