2017-02-16 48 views
17

Я работаю над проектом, в котором я выполняю переадресацию портов в 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-серверу.

ответ

6

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

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

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

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

шаги выше взяты из 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); 

И это все.