2017-02-16 59 views
17

Pracuję nad projektem, w którym wykonuję przekazywanie portów do MySQL przy użyciu biblioteki libssh2 w C++. Mam to działa do uwierzytelniania nazwy użytkownika/hasła, ale teraz chcę zrobić to za pomocą uwierzytelniania klucza publicznego/prywatnego. Dokumentacja dla libssh2 jest dość uboga, więc mam trudną pracę, co muszę zrobić.Autoryzacja klucza publicznego SSH za pomocą Libssh2 C++

Próbuję umieścić dane aplikacji na Androida w mojej aplikacji C++, w której C++ otrzyma szczegóły SSH wraz z kluczem auth i utworzy tunel SSH. C++ uzyskuje klucz dobrze, a następnie wykonuję następujące czynności, aby wykonać uwierzytelnianie klucza publicznego.

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

      } 
     } 
    } 

Czytałem gdzieś, że nie powinno mieć nowe linie, dlatego jestem zastępując \ n dla pustych znaków, ale z lub bez tego nie robi różnicy.

Bardzo Podstawowa dokumentacja wskazuje, że jednym z argumentów za libssh2_userauth_publickey jest zwrotna, co następuje:

int name(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract);

ale nie mogę znaleźć żadnych informacji w dowolnym miejscu, co to zwrotna jest lub co powinien zawierać. W mojej funkcji wywołania libssh2_userauth_publickey mijam w SSHTunnelForwarder::publicKeyAuthComplete a obecnie ta funkcja ma tylko następujące:

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

Ta metoda powyżej nie sprawdzony, choć spodziewam się, że to nie jest nawet blisko jest poprawna .

Po uruchomieniu kodu powyżej wyniku biblioteki libssh2_userauth_publickey jest 19, a błąd zwrócony z metody get_last_message() to invalid public key. Wiem, że plik klucza publicznego jest w porządku, ponieważ mogę go używać w aplikacji SSH na Androida i mogę z powodzeniem uwierzytelnić się na moim serwerze.

Dziękujemy za pomoc.

UPDATE 1

udało mi się zrobić jakiś postęp, znalazłem tam jest funkcja o nazwie:

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

Wersja libssh2 że miałam od kierownika Nuget pakiet i okazało się, że najnowsza wersja jest w rzeczywistości dość stara, dlatego stworzyłem najnowszą wersję 1.7.0 z GitHub w Visual Studio i zrewolucjonizowałem mój projekt do nowej wersji.

Mam teraz zastąpiła pierwotną funkcję publickey auth używałem tej wersji, więc mój kod wygląda teraz tak zamiast:

int result = libssh2_userauth_publickey_frommemory(this->session, username.c_str(), username.length(), nullptr, 0, test.c_str(), sizeofkey, nullptr); 

Funkcja ta myli mnie trochę, że chce klucz publiczny i prywatny klucz, dla wszystkiego, co wiem o SSH (wprawdzie niezbyt wielka ilość) klucz publiczny pozostaje na serwerze, a użytkownik, który chce się zalogować ma dostęp tylko do klucza prywatnego.

Znalazłem, że ktoś inny o to pytał, a łatka została wykonana, aby umożliwić użycie pustego wskaźnika dla klucza publicznego, dlatego przekazałem nullptr dla klucza publicznego i 0 dla klucza publicznego. Wstawiłem również nullptr dla hasła certyfikatu, ponieważ nie zostało to ustawione.

Po uruchomieniu tego kodu otrzymuję teraz błąd -18, który jest invalid username/public key combination. Ponownie, wiem, że nazwa użytkownika i plik klucza prywatnego, którego używam, są poprawne, ponieważ mogę go użyć w aplikacji klienckiej SSH na Androida, aby połączyć się z moim serwerem SSH.

Odpowiedz

6

Znalazłem rozwiązanie. To, co zrobiłem w aktualizacji 1, to rzeczywista poprawka, ale mój klucz serwera został zmieniony z jakiegoś powodu nie wiem dlaczego, więc kiedy powiedział, że nie mógł połączyć nazwy użytkownika z kluczem, to było poprawne.

Kompletny dylemat jest następujący:

Nie używaj libssh2 z Nuget jego bardzo stary. Pobrałem najnowsze źródło z GitHub pod numerem https://github.com/libssh2/libssh2/releases, a następnie wykonałem następujące kroki, aby zbudować bibliotekę libssh2 w Visual Studio.

  • Shove wszystkie .c pliki libssh2/src do pustej Win32 C++ (DLL lub biblioteka statyczna) projektu wyjątkiem libgcrypt.c/openssl.c z którego tylko wybrać ten odpowiedni do biblioteki crypto .
  • Dodaj swoją OpenSSL lub libgcrypt obejmują katalogu z projektem to ścieżka
  • Dodaj libssh2/include do projektu zawierać ścieżkę
  • Dodaj libssh2/win32 do projektu zawierać ścieżkę
  • Dodaj odpowiednich bibliotek kryptograficznych do projektu lista każda dodatkowa biblioteki
  • Zbuduj
  • zadanie

Kroki powyżej pochodzą z https://www.libssh2.org/mail/libssh2-devel-archive-2012-09/0029.shtml

Biblioteka libssh2 została połączona z openssl podczas kompilacji.

Połącz swój projekt do najnowszej kompilacji właśnie wykonanej dla libssh2 i użyć metody

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

I to wszystko.