added private key export without password to client config
This commit is contained in:
parent
f3aef67be6
commit
5e099f522e
10 changed files with 76 additions and 56 deletions
|
@ -13,7 +13,6 @@ struct ServerCredentials
|
||||||
QString hostName;
|
QString hostName;
|
||||||
QString userName;
|
QString userName;
|
||||||
QString password;
|
QString password;
|
||||||
QString decryptedPrivateKey;
|
|
||||||
int port = 22;
|
int port = 22;
|
||||||
|
|
||||||
bool isValid() const { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
|
bool isValid() const { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
|
||||||
|
@ -36,6 +35,7 @@ enum ErrorCode
|
||||||
|
|
||||||
// Ssh connection errors
|
// Ssh connection errors
|
||||||
SshRequsetDeniedError, SshInterruptedError, SshInternalError,
|
SshRequsetDeniedError, SshInterruptedError, SshInternalError,
|
||||||
|
SshPrivateKeyError,
|
||||||
|
|
||||||
// Ssh sftp errors
|
// Ssh sftp errors
|
||||||
SshSftpEofError, SshSftpNoSuchFileError, SshSftpPermissionDeniedError,
|
SshSftpEofError, SshSftpNoSuchFileError, SshSftpPermissionDeniedError,
|
||||||
|
|
|
@ -21,6 +21,7 @@ QString errorString(ErrorCode code){
|
||||||
case(SshRequsetDeniedError): return QObject::tr("Ssh request was denied");
|
case(SshRequsetDeniedError): return QObject::tr("Ssh request was denied");
|
||||||
case(SshInterruptedError): return QObject::tr("Ssh request was interrupted");
|
case(SshInterruptedError): return QObject::tr("Ssh request was interrupted");
|
||||||
case(SshInternalError): return QObject::tr("Ssh internal error");
|
case(SshInternalError): return QObject::tr("Ssh internal error");
|
||||||
|
case(SshPrivateKeyError): return QObject::tr("Invalid private key or invalid passphrase entered");
|
||||||
|
|
||||||
// Libssh sftp errors
|
// Libssh sftp errors
|
||||||
case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered");
|
case(SshSftpEofError): return QObject::tr("Sftp error: End-of-file encountered");
|
||||||
|
|
|
@ -46,7 +46,7 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
||||||
const std::function<ErrorCode (const QString &, libssh::Client &)> &cbReadStdOut,
|
const std::function<ErrorCode (const QString &, libssh::Client &)> &cbReadStdOut,
|
||||||
const std::function<ErrorCode (const QString &, libssh::Client &)> &cbReadStdErr) {
|
const std::function<ErrorCode (const QString &, libssh::Client &)> &cbReadStdErr) {
|
||||||
|
|
||||||
auto error = m_sshClient.connectToHost(credentials, m_passphraseCallback);
|
auto error = m_sshClient.connectToHost(credentials);
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const
|
||||||
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
|
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
|
||||||
libssh::SftpOverwriteMode overwriteMode)
|
libssh::SftpOverwriteMode overwriteMode)
|
||||||
{
|
{
|
||||||
auto error = m_sshClient.connectToHost(credentials, m_passphraseCallback);
|
auto error = m_sshClient.connectToHost(credentials);
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -757,5 +757,11 @@ ErrorCode ServerController::getAlreadyInstalledContainers(const ServerCredential
|
||||||
|
|
||||||
void ServerController::setPassphraseCallback(const std::function<QString()> &callback)
|
void ServerController::setPassphraseCallback(const std::function<QString()> &callback)
|
||||||
{
|
{
|
||||||
m_passphraseCallback = callback;
|
m_sshClient.setPassphraseCallback(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ServerController::getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey)
|
||||||
|
{
|
||||||
|
auto error = m_sshClient.getDecryptedPrivateKey(credentials, decryptedPrivateKey);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap<DockerContainer, QJsonObject> &installedContainers);
|
ErrorCode getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap<DockerContainer, QJsonObject> &installedContainers);
|
||||||
|
|
||||||
void setPassphraseCallback(const std::function<QString()> &callback);
|
void setPassphraseCallback(const std::function<QString()> &callback);
|
||||||
|
ErrorCode getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey);
|
||||||
private:
|
private:
|
||||||
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
||||||
ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||||
|
@ -88,7 +89,6 @@ private:
|
||||||
|
|
||||||
bool m_cancelInstallation = false;
|
bool m_cancelInstallation = false;
|
||||||
libssh::Client m_sshClient;
|
libssh::Client m_sshClient;
|
||||||
std::function<QString()> m_passphraseCallback;
|
|
||||||
signals:
|
signals:
|
||||||
void serverIsBusy(const bool isBusy);
|
void serverIsBusy(const bool isBusy);
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,15 +25,8 @@ namespace libssh {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode Client::connectToHost(const ServerCredentials &credentials, const std::function<QString()> &passphraseCallback)
|
ErrorCode Client::connectToHost(const ServerCredentials &credentials)
|
||||||
{
|
{
|
||||||
// if (is_ssh_initialized()) {
|
|
||||||
// qDebug() << "Failed to initialize ssh";
|
|
||||||
// return ErrorCode::InternalError;
|
|
||||||
// }
|
|
||||||
|
|
||||||
m_passphraseCallback = passphraseCallback;
|
|
||||||
|
|
||||||
if (m_session == nullptr) {
|
if (m_session == nullptr) {
|
||||||
m_session = ssh_new();
|
m_session = ssh_new();
|
||||||
|
|
||||||
|
@ -64,39 +57,20 @@ namespace libssh {
|
||||||
int authResult = SSH_ERROR;
|
int authResult = SSH_ERROR;
|
||||||
if (credentials.password.contains("BEGIN") && credentials.password.contains("PRIVATE KEY")) {
|
if (credentials.password.contains("BEGIN") && credentials.password.contains("PRIVATE KEY")) {
|
||||||
ssh_key privateKey;
|
ssh_key privateKey;
|
||||||
authResult = ssh_pki_import_privkey_base64(credentials.password.toStdString().c_str(), nullptr, callback, nullptr, &privateKey);
|
|
||||||
if (authResult != SSH_OK) {
|
|
||||||
qDebug() << ssh_get_error(m_session);
|
|
||||||
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_key publicKey;
|
ssh_key publicKey;
|
||||||
|
authResult = ssh_pki_import_privkey_base64(credentials.password.toStdString().c_str(), nullptr, callback, nullptr, &privateKey);
|
||||||
|
if (authResult == SSH_OK) {
|
||||||
authResult = ssh_pki_export_privkey_to_pubkey(privateKey, &publicKey);
|
authResult = ssh_pki_export_privkey_to_pubkey(privateKey, &publicKey);
|
||||||
if (authResult != SSH_OK) {
|
|
||||||
qDebug() << ssh_get_error(m_session);
|
|
||||||
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (authResult == SSH_OK) {
|
||||||
authResult = ssh_userauth_try_publickey(m_session, authUsername.c_str(), publicKey);
|
authResult = ssh_userauth_try_publickey(m_session, authUsername.c_str(), publicKey);
|
||||||
if (authResult != SSH_OK) {
|
|
||||||
qDebug() << ssh_get_error(m_session);
|
|
||||||
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (authResult == SSH_OK) {
|
||||||
authResult = ssh_userauth_publickey(m_session, authUsername.c_str(), privateKey);
|
authResult = ssh_userauth_publickey(m_session, authUsername.c_str(), privateKey);
|
||||||
if (authResult != SSH_OK) {
|
|
||||||
qDebug() << ssh_get_error(m_session);
|
|
||||||
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* key = new char[65535];
|
|
||||||
authResult = ssh_pki_export_privkey_base64(privateKey, nullptr, nullptr, nullptr, &key);
|
|
||||||
if (authResult != SSH_OK) {
|
|
||||||
qDebug() << ssh_get_error(m_session);
|
|
||||||
return fromLibsshErrorCode(ssh_get_error_code(m_session));
|
|
||||||
}
|
|
||||||
|
|
||||||
// credentials.decryptedPrivateKey(key);
|
|
||||||
|
|
||||||
ssh_key_free(publicKey);
|
ssh_key_free(publicKey);
|
||||||
ssh_key_free(privateKey);
|
ssh_key_free(privateKey);
|
||||||
} else {
|
} else {
|
||||||
|
@ -363,4 +337,35 @@ namespace libssh {
|
||||||
default: return ErrorCode::SshSftpFailureError;
|
default: return ErrorCode::SshSftpFailureError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorCode Client::getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey)
|
||||||
|
{
|
||||||
|
int authResult = SSH_ERROR;
|
||||||
|
ErrorCode errorCode = ErrorCode::NoError;
|
||||||
|
|
||||||
|
ssh_key privateKey;
|
||||||
|
authResult = ssh_pki_import_privkey_base64(credentials.password.toStdString().c_str(), nullptr, callback, nullptr, &privateKey);
|
||||||
|
if (authResult == SSH_OK) {
|
||||||
|
char* key = new char[65535];
|
||||||
|
|
||||||
|
authResult = ssh_pki_export_privkey_base64(privateKey, nullptr, nullptr, nullptr, &key);
|
||||||
|
decryptedPrivateKey = key;
|
||||||
|
delete[] key;
|
||||||
|
|
||||||
|
if (authResult != SSH_OK) {
|
||||||
|
qDebug() << "failed to export private key";
|
||||||
|
errorCode = ErrorCode::InternalError;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorCode = ErrorCode::SshPrivateKeyError;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_key_free(privateKey);
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setPassphraseCallback(const std::function<QString()> &callback)
|
||||||
|
{
|
||||||
|
m_passphraseCallback = callback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace libssh {
|
||||||
Client(QObject *parent = nullptr);
|
Client(QObject *parent = nullptr);
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
ErrorCode connectToHost(const ServerCredentials &credentials, const std::function<QString()> &passphraseCallback);
|
ErrorCode connectToHost(const ServerCredentials &credentials);
|
||||||
void disconnectFromHost();
|
void disconnectFromHost();
|
||||||
ErrorCode executeCommand(const QString &data,
|
ErrorCode executeCommand(const QString &data,
|
||||||
const std::function<ErrorCode (const QString &, Client &)> &cbReadStdOut,
|
const std::function<ErrorCode (const QString &, Client &)> &cbReadStdOut,
|
||||||
|
@ -36,6 +36,8 @@ namespace libssh {
|
||||||
const std::string& localPath,
|
const std::string& localPath,
|
||||||
const std::string& remotePath,
|
const std::string& remotePath,
|
||||||
const std::string& fileDesc);
|
const std::string& fileDesc);
|
||||||
|
ErrorCode getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey);
|
||||||
|
void setPassphraseCallback(const std::function<QString()> &callback);
|
||||||
private:
|
private:
|
||||||
ErrorCode closeChannel();
|
ErrorCode closeChannel();
|
||||||
ErrorCode closeSftpSession();
|
ErrorCode closeSftpSession();
|
||||||
|
|
|
@ -165,6 +165,6 @@
|
||||||
<file>ui/qml/Controls/PopupWithQuestion.qml</file>
|
<file>ui/qml/Controls/PopupWithQuestion.qml</file>
|
||||||
<file>ui/qml/Pages/PageAdvancedServerSettings.qml</file>
|
<file>ui/qml/Pages/PageAdvancedServerSettings.qml</file>
|
||||||
<file>ui/qml/Controls/PopupWarning.qml</file>
|
<file>ui/qml/Controls/PopupWarning.qml</file>
|
||||||
<file>ui/qml/Controls/PopupWithInputField.qml</file>
|
<file>ui/qml/Controls/PopupWithTextField.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "configurators/vpn_configurator.h"
|
#include "configurators/vpn_configurator.h"
|
||||||
#include "../uilogic.h"
|
#include "../uilogic.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
#include "core/servercontroller.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
@ -94,8 +95,7 @@ void StartPageLogic::onPushButtonConnect()
|
||||||
set_labelWaitInfoText(tr("Please fill in all fields"));
|
set_labelWaitInfoText(tr("Please fill in all fields"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (lineEditIpText().isEmpty() ||
|
if (lineEditIpText().isEmpty() ||
|
||||||
lineEditLoginText().isEmpty() ||
|
lineEditLoginText().isEmpty() ||
|
||||||
lineEditPasswordText().isEmpty() ) {
|
lineEditPasswordText().isEmpty() ) {
|
||||||
|
@ -123,28 +123,34 @@ void StartPageLogic::onPushButtonConnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
serverCredentials.password = key;
|
serverCredentials.password = key;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
serverCredentials.password = lineEditPasswordText();
|
serverCredentials.password = lineEditPasswordText();
|
||||||
}
|
}
|
||||||
|
|
||||||
set_pushButtonConnectEnabled(false);
|
set_pushButtonConnectEnabled(false);
|
||||||
set_pushButtonConnectText(tr("Connecting..."));
|
set_pushButtonConnectText(tr("Connecting..."));
|
||||||
|
|
||||||
ErrorCode e = ErrorCode::NoError;
|
ErrorCode errorCode = ErrorCode::NoError;
|
||||||
#ifdef Q_DEBUG
|
#ifdef Q_DEBUG
|
||||||
//QString output = m_serverController->checkSshConnection(serverCredentials, &e);
|
//QString output = m_serverController->checkSshConnection(serverCredentials, &e);
|
||||||
#else
|
#else
|
||||||
QString output;
|
QString output;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ok = true;
|
if (pushButtonConnectKeyChecked()) {
|
||||||
if (e) {
|
QString decryptedPrivateKey;
|
||||||
set_labelWaitInfoVisible(true);
|
errorCode = uiLogic()->m_serverController->getDecryptedPrivateKey(serverCredentials, decryptedPrivateKey);
|
||||||
set_labelWaitInfoText(errorString(e));
|
if (errorCode == ErrorCode::NoError) {
|
||||||
ok = false;
|
serverCredentials.password = decryptedPrivateKey;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
if (errorCode) {
|
||||||
|
set_labelWaitInfoVisible(true);
|
||||||
|
set_labelWaitInfoText(errorString(errorCode));
|
||||||
|
ok = false;
|
||||||
|
} else {
|
||||||
if (output.contains("Please login as the user")) {
|
if (output.contains("Please login as the user")) {
|
||||||
output.replace("\n", "");
|
output.replace("\n", "");
|
||||||
set_labelWaitInfoVisible(true);
|
set_labelWaitInfoVisible(true);
|
||||||
|
|
|
@ -235,7 +235,7 @@ Window {
|
||||||
popupWarning.open()
|
popupWarning.open()
|
||||||
}
|
}
|
||||||
function onShowPassphraseRequestMessage() {
|
function onShowPassphraseRequestMessage() {
|
||||||
popupWithInputField.open()
|
popupWithTextField.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,8 +358,8 @@ Window {
|
||||||
PopupWarning {
|
PopupWarning {
|
||||||
id: popupWarning
|
id: popupWarning
|
||||||
}
|
}
|
||||||
PopupWithInputField {
|
PopupWithTextField {
|
||||||
id: popupWithInputField
|
id: popupWithTextField
|
||||||
placeholderText: "Enter private key passphrase"
|
placeholderText: "Enter private key passphrase"
|
||||||
yesFunc: function() {
|
yesFunc: function() {
|
||||||
editingFinished()
|
editingFinished()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue