ikev2 impl for windows
This commit is contained in:
parent
8084b2764a
commit
64e5e02744
2 changed files with 196 additions and 8 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "ikev2_vpn_protocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
|
@ -25,34 +26,193 @@ Ikev2Protocol::~Ikev2Protocol()
|
|||
|
||||
void Ikev2Protocol::stop()
|
||||
{
|
||||
#ifndef Q_OS_IOS
|
||||
#ifdef Q_OS_WINDOWS
|
||||
{
|
||||
setConnectionState(Disconnecting);
|
||||
|
||||
auto disconnectProcess = new QProcess;
|
||||
|
||||
disconnectProcess->setProgram("rasdial");
|
||||
QString arguments = QString("\"%1\" /disconnect")
|
||||
.arg(tunnelName());
|
||||
disconnectProcess->setNativeArguments(arguments);
|
||||
|
||||
// connect(connectProcess, &QProcess::readyRead, [connectProcess]() {
|
||||
// qDebug().noquote() << "connectProcess readyRead" << connectProcess->readAll();
|
||||
// });
|
||||
|
||||
disconnectProcess->start();
|
||||
disconnectProcess->waitForFinished(5000);
|
||||
setConnectionState(Disconnected);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration)
|
||||
{
|
||||
QString cfgData = configuration.value(ProtocolProps::key_proto_config_data(Protocol::Ikev2)).toString();
|
||||
m_config = QJsonDocument::fromJson(cfgData.toUtf8()).object();
|
||||
m_config = configuration.value(ProtocolProps::key_proto_config_data(Protocol::Ikev2)).toObject();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ErrorCode Ikev2Protocol::start()
|
||||
{
|
||||
#ifndef Q_OS_IOS
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QByteArray cert = QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8());
|
||||
qDebug() << "Ikev2Protocol::start()" << cert;
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
|
||||
QTemporaryFile certFile;
|
||||
certFile.setAutoRemove(false);
|
||||
certFile.open();
|
||||
certFile.write(cert);
|
||||
certFile.close();
|
||||
|
||||
|
||||
{
|
||||
auto certInstallProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!certInstallProcess) {
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
certInstallProcess->waitForSource(1000);
|
||||
if (!certInstallProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
certInstallProcess->setProgram("certutil");
|
||||
QStringList arguments({"-f" , "-importpfx",
|
||||
"-p", m_config[config_key::password].toString(),
|
||||
certFile.fileName(), "NoExport"
|
||||
});
|
||||
certInstallProcess->setArguments(arguments);
|
||||
|
||||
// qDebug() << arguments.join(" ");
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, [certInstallProcess](QProcess::ProcessError error) {
|
||||
// qDebug() << "IpcProcessInterfaceReplica errorOccurred" << error;
|
||||
// });
|
||||
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::stateChanged, [certInstallProcess](QProcess::ProcessState newState) {
|
||||
// qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState;
|
||||
// });
|
||||
|
||||
// connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::readyRead, [certInstallProcess]() {
|
||||
// auto req = certInstallProcess->readAll();
|
||||
// req.waitForFinished();
|
||||
// qDebug() << "IpcProcessInterfaceReplica readyRead" << req.returnValue();
|
||||
// });
|
||||
|
||||
|
||||
certInstallProcess->start();
|
||||
}
|
||||
|
||||
{
|
||||
auto adapterRemoveProcess = new QProcess;
|
||||
|
||||
adapterRemoveProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Remove-VpnConnection -Name '%1' -Force\"").arg(tunnelName());
|
||||
adapterRemoveProcess->setNativeArguments(arguments);
|
||||
|
||||
adapterRemoveProcess->start();
|
||||
adapterRemoveProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
{
|
||||
auto adapterInstallProcess = new QProcess;
|
||||
|
||||
adapterInstallProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Add-VpnConnection "
|
||||
"-ServerAddress '%1' "
|
||||
"-Name '%2' "
|
||||
"-TunnelType IKEv2 "
|
||||
"-AuthenticationMethod MachineCertificate "
|
||||
"-EncryptionLevel Required "
|
||||
"-PassThru\"")
|
||||
.arg(m_config[config_key::hostName].toString())
|
||||
.arg(tunnelName());
|
||||
adapterInstallProcess->setNativeArguments(arguments);
|
||||
// connect(adapterInstallProcess, &QProcess::readyRead, [adapterInstallProcess]() {
|
||||
// qDebug().noquote() << "adapterInstallProcess readyRead" << adapterInstallProcess->readAll();
|
||||
// });
|
||||
|
||||
adapterInstallProcess->start();
|
||||
adapterInstallProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
{
|
||||
auto adapterConfigProcess = new QProcess;
|
||||
|
||||
adapterConfigProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Set-VpnConnectionIPsecConfiguration\ "
|
||||
"-ConnectionName '%1'\ "
|
||||
"-AuthenticationTransformConstants GCMAES128 "
|
||||
"-CipherTransformConstants GCMAES128 "
|
||||
"-EncryptionMethod AES256 "
|
||||
"-IntegrityCheckMethod SHA256 "
|
||||
"-PfsGroup None "
|
||||
"-DHGroup Group14 "
|
||||
"-PassThru -Force\"")
|
||||
.arg(tunnelName());
|
||||
adapterConfigProcess->setNativeArguments(arguments);
|
||||
|
||||
// connect(adapterConfigProcess, &QProcess::readyRead, [adapterConfigProcess]() {
|
||||
// qDebug().noquote() << "adapterConfigProcess readyRead" << adapterConfigProcess->readAll();
|
||||
// });
|
||||
|
||||
adapterConfigProcess->start();
|
||||
adapterConfigProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
{
|
||||
// char buf[RASBUFFER]= {0};
|
||||
// DWORD err = 0;
|
||||
// RASDIALPARAMSA *param = (RASDIALPARAMSA *)buf;
|
||||
// param->dwSize = 1064;
|
||||
// strcpy(param->szEntryName, tunnelName().toStdString().c_str());
|
||||
// err = RasDialA(NULL, NULL, param, 0, (LPVOID)rasCallback, &g_h);
|
||||
// qDebug() << "Ikev2Protocol::start() ret" << err;
|
||||
|
||||
|
||||
auto connectProcess = new QProcess;
|
||||
|
||||
connectProcess->setProgram("rasdial");
|
||||
QString arguments = QString("\"%1\"")
|
||||
.arg(tunnelName());
|
||||
connectProcess->setNativeArguments(arguments);
|
||||
|
||||
connect(connectProcess, &QProcess::readyRead, [connectProcess]() {
|
||||
qDebug().noquote() << "connectProcess readyRead" << connectProcess->readAll();
|
||||
});
|
||||
|
||||
connectProcess->start();
|
||||
connectProcess->waitForFinished(5000);
|
||||
}
|
||||
|
||||
setConnectionState(Connected);
|
||||
return ErrorCode::NoError;
|
||||
|
||||
#endif
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
DWORD CALLBACK rasCallback(UINT msg, RASCONNSTATE rascs, DWORD err)
|
||||
{
|
||||
if(err != 0) {
|
||||
printf("Error: %d\n", err);
|
||||
fflush(stdout);
|
||||
//g_done = 1;
|
||||
return 0; // stop the connection.
|
||||
} else {
|
||||
//printf("%s\n", rasState(rascs));
|
||||
fflush(stdout);
|
||||
if(rascs == RASCS_Connected) {
|
||||
printf("Success: Connected\n");
|
||||
fflush(stdout);
|
||||
//g_done = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,23 @@
|
|||
#include "vpnprotocol.h"
|
||||
#include "core/ipcclient.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <ras.h>
|
||||
#include <raserror.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
#pragma comment(lib, "rasapi32.lib")
|
||||
|
||||
#define RASBUFFER 0x1000
|
||||
#define RASMAXENUM 0x100
|
||||
#endif
|
||||
|
||||
class Ikev2Protocol : public VpnProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -21,12 +38,23 @@ public:
|
|||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
static QString tunnelName() { return "AmneziaVPN IKEv2"; }
|
||||
|
||||
private:
|
||||
void readIkev2Configuration(const QJsonObject &configuration);
|
||||
|
||||
|
||||
private:
|
||||
QJsonObject m_config;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
HRASCONN g_h;
|
||||
int g_done = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
DWORD CALLBACK rasCallback(UINT msg, RASCONNSTATE rascs, DWORD err);
|
||||
#endif
|
||||
|
||||
#endif // IPSEC_PROTOCOL_H
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue