Я работаю над проектом, в котором я выполняю переадресацию портов в MySQL, используя libssh2 в C++. У меня есть работа для аутентификации имени пользователя и пароля, но теперь я хочу сделать это с помощью проверки подлинности с открытым/закрытым ключом. Документация для libssh2 довольно бедна, поэтому мне сложно разобраться в том, что мне нужно делать.SSH Public Key Authentication with Libssh2 C++
То, что я пытаюсь сделать, это иметь данные для отправки сообщений на Android в мое приложение на C++, где C++ будет предоставлена информация SSH вместе с ключом auth и создаст туннель SSH. C++ получает ключ отлично, а затем я делаю следующее для аутентификации с открытым ключом.
else if (this->getAuthMethod() == SupportedAuthMethods::AUTH_PUBLICKEY)
{
string test = this->getSSHPrivateKey();
boost::replace_all(test, "\n", "");
unsigned char * key = (unsigned char *)test.c_str();
size_t sizeofkey = strlen((char*)key);
cout << key << endl;
stringstream logstream;
logstream << "Using public key authentication for SSH Host: " << this->getSSHHostnameOrIPAddress();
this->bitsLibrary->writeToLog(logstream.str(), "SSHTunnelForwarder", "authenticateSSHServer");
if (chosenAuthMethod & SupportedAuthMethods::AUTH_PUBLICKEY)
{
//int result = 0;
int result = libssh2_userauth_publickey(this->session, this->getUsername().c_str(), key, sizeofkey, SSHTunnelForwarder::publicKeyAuthComplete, 0);
if (result != 0)
{
char * error = NULL;
int len = 0;
int errbuf = 0;
libssh2_session_last_error(this->session, &error, &len, errbuf);
this->bitsLibrary->writeToLog(std::string(error), "SSHTunnelForwarder", "auth");
JSONResponseGenerator jsonResponse;
jsonResponse.generateJSONResponse(API_AUTH_FAILURE, "InvalidPublicKey");
return jsonResponse.getJSONString();
}
}
}
Я где-то читал, что он не должен иметь новые линии, поэтому я заменить \ N пустых символов, но с или без этого не делает разницы.
Сама основная документация упоминает, что один из аргументов libssh2_userauth_publickey
является обратного вызова следующим образом:
int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract);
, но я не могу найти любую информацию в любом месте, как к тому, что этот обратный вызов или то, что она должна содержать. В моем вызове функции в libssh2_userauth_publickey я прохожу в SSHTunnelForwarder::publicKeyAuthComplete
и в настоящее время эта функция только имеет следующее:
int SSHTunnelForwarder::publicKeyAuthComplete(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
const unsigned char *data, size_t data_len, void **abstract)
{
cout << "In SSH Auth Callback" << endl;
return 0;
}
Этот метод выше не дозвонился, хотя я ожидал, что это даже не близко к правильному, ,
Когда я запускаю свой код выше результата libssh2_userauth_publickey, равно 19, и ошибка, возвращаемая из метода get_last_message()
, равна invalid public key
. Я знаю, что файл открытого ключа прекрасен, так как я могу использовать его в приложении SSH на Android и могу успешно пройти аутентификацию с моего сервера.
Спасибо за любую помощь, которую вы можете предоставить.
UPDATE 1
мне удалось добиться определенного прогресса, я обнаружил, есть функция называется:
libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session, const char *username, size_t username_len, const char *publickeyfiledata, size_t publickeyfiledata_len, const char *privatekeyfiledata, size_t privatekeyfiledata_len, const char *passphrase);
версия libssh2, что у меня было от менеджера NuGet пакетов и обнаружил, что последняя версия в этом на самом деле довольно старая, поэтому я создал последнюю версию 1.7.0 от GitHub внутри Visual Studio и перенаправил свой проект на эту новую версию.
Я теперь заменили первоначальную функцию ОткрытыйКлюч аутентификации я использовал с этой версией так что мой код теперь выглядит следующим образом, вместо:
int result = libssh2_userauth_publickey_frommemory(this->session, username.c_str(), username.length(), nullptr, 0, test.c_str(), sizeofkey, nullptr);
Эта функция меня смущает немного, что он хочет, открытый ключ и частный ключ, для всего, что я знаю о SSH (допустимо не огромное количество), открытый ключ остается на сервере, и пользователь, желающий войти в систему, имеет доступ только к закрытому ключу.
Я обнаружил, что кто-то спрашивал об этом, и был сделан патч, чтобы разрешить пустой указатель для открытого ключа, поэтому я передал nullptr для открытого ключа и 0 для длины открытого ключа. Я также поместил nullptr для кодовой фразы сертификата, поскольку это не было установлено.
Когда я запускаю этот код, теперь я получаю ошибку -18, которая равна invalid username/public key combination
. Опять же, я знаю, что имя пользователя и файл закрытого ключа, который я использую, верны, поскольку я могу использовать его в клиентском приложении SSH на Android для подключения к моему SSH-серверу.