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.