2013-02-19 85 views
3

我使用libssh2来使联网程序更安全。如果密钥请求被接受,libssh2公钥认证只需要密码

我想我的程序以类似于OpenSSH客户端ssh(1)的方式进行身份验证。 OpenSSH客户端只会要求服务器实际接受密钥的密码。

据我所知,从this link,SSH客户端发送请求使用公钥,如果接受,它可以解锁使用密码的私钥。

libssh2提供了一个函数libssh2_userauth_publickey_fromfile,它使用私钥和公钥文件名以及密码。使用这个函数是非常直接的,但这意味着即使公钥没有被服务器首先接受,我也必须获得私钥的密码。对于拥有许多不同密钥的用户来说,这显然是一个问题(我的程序目前正在迭代〜/ .ssh目录中的密钥文件)。

我曾尝试阅读libssh2函数的手册页,其中大多数对于我来说太简短了,没有对ssh协议的更详细的了解。实际上some of them甚至还没有被写入。

任何人都可以告诉我如何只提示输入密码的密码,这些密码实际上是由ssh服务器使用libssh2接受的?

回答

3

经过RTFM和做了一些测试后,我发现libssh2_userauth_publickey_fromfile将返回一个不同的错误代码,具体取决于密钥未被服务器接受还是密码错误。

因此,这是一个相当低效的解决方案(因为它调用libssh2_userauth_publickey_fromfile,因此协议的所有密钥交换部分至少需要两次)。

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); 
} 

为了完整起见,​​函数使用溶液来this question提示输入密码短语用户。