Подтвердить что ты не робот

Аутентификация открытого ключа SSH с помощью Libssh2 С++

Я работаю над проектом, в котором я выполняю переадресацию портов в MySQL, используя libssh2 в С++. У меня есть работа для аутентификации имени пользователя и пароля, но теперь я хочу сделать это с помощью проверки подлинности с открытым/закрытым ключом. Документация для libssh2 довольно бедна, поэтому мне сложно разобраться в том, что мне нужно делать.

То, что я пытаюсь сделать, это отправить данные приложения Android на мое приложение на С++, где С++ будет предоставлена ​​информация SSH вместе с ключом auth и создаст туннель SSH. С++ получает ключ отлично, а затем я делаю следующее для аутентификации с открытым ключом.

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 и могу успешно пройти аутентификацию с моего сервера.

Спасибо за любую помощь, которую вы можете предоставить.

ОБНОВЛЕНИЕ 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 и перенаправил свой проект на этот новый версия.

Теперь я заменил оригинальную функцию autick для публики, которую я использовал с этой версией, поэтому теперь мой код выглядит следующим образом:

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-серверу.

4b9b3361

Ответ 1

Я нашел решение. То, что я сделал в обновлении 1, было фактическим исправлением, но мой ключ сервера был изменен по какой-то причине, не знаю почему, поэтому, когда он сказал, что он не может связать имя пользователя с ключом, это было правильно.

Полное исправление выглядит следующим образом:

Не используйте libssh2 из NuGet его самого старого. Я загрузил последний источник из GitHub в https://github.com/libssh2/libssh2/releases, а затем выполнил следующие шаги для создания libssh2 в Visual Studio.

  • Перетащите все .c файлы в libssh2/src в пустой Win32 С++ (DLL или Static Library), за исключением libgcrypt.c/openssl.c, из которых вы выберите только тот, который соответствует вашей криптографической библиотеке.
  • Добавьте каталог OpenSSL или libgcrypt include в проект, включая путь
  • Добавить libssh2/include в проект include path
  • Добавить libssh2/win32 в проект include path
  • Добавить соответствующие криптографические библиотеки в список дополнительных библиотек проекта
  • Построить
  • Работа выполнена

Шаги, взятые из https://www.libssh2.org/mail/libssh2-devel-archive-2012-09/0029.shtml

libssh2 был связан с openssl во время компиляции.

Свяжите свой проект с последней сборкой, которую вы только что сделали для libssh2, и используйте метод

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

И что это.