Libssh2 public key authentication only requires passphrase if a key request is accepted

I am using libssh2

to make a network program more secure.

I want my program to authenticate as close as possible to the ssh (1) OpenSSH client. The OpenSSH client will only ask for passphrases for keys that are actually accepted by the server.

As I understand from this link , the ssh client sends a request to use the public key, and if accepted, it can unlock the private key using a passphrase.

libssh2 provides a function libssh2_userauth_publickey_fromfile

that accepts private and public key file names and passphrase. Using this function is very straight forward, but it means that I have to get the passphrase for the private keys, even if the public key would not have been accepted by the server in the first place. This is clearly a problem for users who have many different keys (my program is currently iterating through the key files in the ~ / .ssh directory).

I've tried reading the man pages for functions libssh2

and most of them seem too short for me to understand without having a more detailed knowledge of the ssh protocol. In fact, some of them have not yet been written.

Can anyone tell me how to only query for key phrases that are actually accepted by the ssh server using libssh2

?

+3


source to share


1 answer


After RTFM and doing some testing, I found that I libssh2_userauth_publickey_fromfile

would return a different error code depending on whether the key was not accepted by the server or the passphrase was incorrect.

So, here is a rather inefficient solution (because it calls libssh2_userauth_publickey_fromfile

and therefore all key parts of the protocol exchange at least twice).



int nAttempts = 3; // number of attempts the user gets at entering the passphrase

// Try authenticating with an empty passphrase
int err = libssh2_userauth_publickey_fromfile(session, user, pub, priv,"");
if (err == 0)
{
    fprintf(stderr, "You shouldn't use keys with an empty passphrase!\n");
}
else if (err == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED)
{
    // if we get here it means the public key was initially accepted
    // but the private key has a non-empty passphrase
    char p[BUFSIZ];

    for (int i = 0; i < nAttempts; ++i)
    {
         get_passphrase(p); // assume this gets the passphrase
         err = libssh2_userauth_publickey_fromfile(session, user, pub, priv,p);
         if (err != LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) break;
    }
}

if (err != 0)
{
    fprintf(stderr, "Authentication using key %s failed!\n", priv);
}

      

For completeness, the function get_passphrase

uses the solution to this question to prompt the user for a passphrase.

+3


source







All Articles