383 lines
12 KiB
C++
383 lines
12 KiB
C++
#include <QProcess>
|
|
#include <QDebug>
|
|
#include <QRegularExpression>
|
|
#include <QRegularExpressionMatchIterator>
|
|
#include <QCoreApplication>
|
|
#include <QOperatingSystemVersion>
|
|
|
|
#include "tapcontroller_win.h"
|
|
|
|
#define TAP_EXE_ERROR { \
|
|
qDebug() << "TapController: Can't start tapinstall.exe"; \
|
|
return false; \
|
|
}
|
|
|
|
#define TAP_NO_MATCHING_DEVICES_ERROR { \
|
|
qDebug() << "TapController: No matching devices found"; \
|
|
return false; \
|
|
}
|
|
|
|
TapController &TapController::Instance()
|
|
{
|
|
static TapController s;
|
|
return s;
|
|
}
|
|
|
|
TapController::TapController()
|
|
{
|
|
}
|
|
|
|
bool TapController::checkInstaller()
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "/?");
|
|
if(!tapInstallProc.waitForStarted()) return false;
|
|
else return true;
|
|
}
|
|
|
|
bool TapController::enableTapAdapter(const QString &tapInstanceId)
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "enable" << QString("@") + tapInstanceId);
|
|
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
|
|
|
tapInstallProc.waitForFinished();
|
|
QString output = QString(tapInstallProc.readAll());
|
|
if (! output.contains("are enabled")) {
|
|
qDebug() << "TapController: Failed to enable tap device";
|
|
return false;
|
|
}
|
|
if (output.contains("No matching devices ")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
|
|
|
qDebug() << "Enabled TAP Instance id:" << tapInstanceId;
|
|
return true;
|
|
}
|
|
|
|
bool TapController::disableTapAdapter(const QString &tapInstanceId)
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "disable" << QString("@") + tapInstanceId);
|
|
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
|
|
|
tapInstallProc.waitForFinished();
|
|
QString output = QString(tapInstallProc.readAll());
|
|
if (! output.contains("disabled")) {
|
|
qDebug() << "TapController: Failed to disable tap device";
|
|
return false;
|
|
}
|
|
if (output.contains("No matching devices ")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
|
|
|
qDebug() << "Disabled TAP Instance id:" << tapInstanceId;
|
|
return true;
|
|
}
|
|
|
|
QStringList TapController::getTapList()
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "find" << "tap0901" );
|
|
if(!tapInstallProc.waitForStarted()) {
|
|
qDebug() << "TapController: TapController: Can't start tapinstall.exe";
|
|
return QStringList();
|
|
}
|
|
tapInstallProc.waitForFinished();
|
|
QString output = QString( tapInstallProc.readAll() );
|
|
output.replace("\r", "");
|
|
if (output.contains("No matched devices found")) {
|
|
qDebug() << "TapController: No matching device instances found";
|
|
return QStringList();
|
|
}
|
|
|
|
QStringList l = output.split("\n", Qt::SkipEmptyParts);
|
|
if (l.size() > 0) l.removeLast();
|
|
|
|
QStringList tapList;
|
|
for (QString s : l) {
|
|
if (s.contains(" ")) tapList.append(s.split(" ", Qt::SkipEmptyParts).first());
|
|
else tapList.append(s);
|
|
}
|
|
|
|
if (! tapList.isEmpty()) {
|
|
enableTapAdapter(tapList.first());
|
|
}
|
|
|
|
return tapList;
|
|
}
|
|
|
|
bool TapController::checkAndSetup()
|
|
{
|
|
qDebug().noquote() << "OpenVPN path" << getOpenVpnPath();
|
|
qDebug().noquote() << "TapInstall path" << getTapInstallPath();
|
|
qDebug().noquote() << "TapDriverDir path" << getTapDriverDir();
|
|
//////////////////////////////////////////////
|
|
/// Check if OpenVPN executable ready for use
|
|
bool isOpenVpnExeExist = checkOpenVpn();
|
|
if (!isOpenVpnExeExist) {
|
|
qDebug() << "TapController::checkAndSetup :::: openvpn.exe not found";
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
/// Check if any TAP adapter ready for use
|
|
bool isAnyAvailableTap = false;
|
|
QStringList tapList = getTapList();
|
|
for (const QString &tap : tapList) {
|
|
qDebug() << "TapController: Found TAP device" << tap << ", checking...";
|
|
if (checkDriver(tap)) {
|
|
isAnyAvailableTap = true;
|
|
qDebug() << "TapController: Device" << tap << "is ready for using";
|
|
}
|
|
else
|
|
qDebug() << "TapController: Device" << tap << "is NOT ready for using";
|
|
}
|
|
|
|
if (isAnyAvailableTap) {
|
|
qDebug() << "TapController: Check success, found usable TAP adapter";
|
|
return true;
|
|
}
|
|
else qDebug() << "TapController: Check failed, usable TAP adapter NOT found";
|
|
|
|
/// Try to setup driver if it's not installed
|
|
qDebug() << "TapController: Installing TAP driver...";
|
|
bool ok = setupDriver();
|
|
|
|
if (QSysInfo::prettyProductName().contains("Server 2008")) {
|
|
restartTapService();
|
|
}
|
|
|
|
if (ok) qDebug() << "TapController: TAP driver successfully installed";
|
|
else qDebug() << "TapController: Failed to install TAP driver";
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool TapController::checkDriver(const QString& tapInstanceId)
|
|
{
|
|
/// Check for driver nodes
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "drivernodes" << QString("@") + tapInstanceId);
|
|
if (!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
|
tapInstallProc.waitForFinished(1000);
|
|
|
|
QString output = QString(tapInstallProc.readAll());
|
|
if (output.contains("No driver nodes found")) {
|
|
qDebug() << "TapController: No driver nodes found";
|
|
return false;
|
|
}
|
|
if (output.contains("No matching devices")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
|
}
|
|
|
|
|
|
/// Check for files
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "driverfiles" << QString("@") + tapInstanceId);
|
|
if (!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
|
tapInstallProc.waitForFinished(1000);
|
|
|
|
QString output = QString(tapInstallProc.readAll());
|
|
if (output.contains("No driver information")) {
|
|
qDebug() << "TapController: No driver information";
|
|
return false;
|
|
}
|
|
if (output.contains("No matching devices")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
|
}
|
|
|
|
/// Check if network adapter enabled
|
|
bool isDisabled = false;
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "status" << QString("@") + tapInstanceId);
|
|
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
|
|
|
tapInstallProc.waitForFinished();
|
|
QString output = QString(tapInstallProc.readAll());
|
|
output.replace("\r", "");
|
|
|
|
if (output.contains("No matching devices ")) TAP_NO_MATCHING_DEVICES_ERROR ;
|
|
|
|
if (output.contains("is running")) {
|
|
qDebug() << "TapController: Device" << tapInstanceId << "is active and ready";
|
|
//return true;
|
|
}
|
|
else if (output.contains("is disabled")) isDisabled = true;
|
|
else {
|
|
qDebug() << "TapController: Device" << tapInstanceId << "is in unknown state";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Disable adapter if enabled
|
|
if (!isDisabled) {
|
|
qDebug() << "TapController: Device" << tapInstanceId << "is enabled. Disabling before use...";
|
|
if (!disableTapAdapter(tapInstanceId)) return false;
|
|
}
|
|
|
|
/// Enable adapter
|
|
{
|
|
qDebug() << "TapController: Device" << tapInstanceId << "is disabled. Enabling...";
|
|
if (!enableTapAdapter(tapInstanceId)) return false;
|
|
}
|
|
|
|
/// Check again
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "status" << QString("@") + tapInstanceId);
|
|
if(!tapInstallProc.waitForStarted()) TAP_EXE_ERROR ;
|
|
|
|
tapInstallProc.waitForFinished();
|
|
QString output = QString(tapInstallProc.readAll());
|
|
|
|
if (output.contains("is running")) return true;
|
|
else {
|
|
qDebug() << "TapController: tap device final check failed";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool TapController::checkOpenVpn()
|
|
{
|
|
/// Check openvpn executable
|
|
QProcess openVpnProc;
|
|
openVpnProc.start(getOpenVpnPath(), QStringList() << "--version");
|
|
if (!openVpnProc.waitForStarted()) {
|
|
qDebug() << "TapController: openvpn.exe NOT found";
|
|
return false;
|
|
}
|
|
openVpnProc.waitForFinished(1000);
|
|
|
|
QString output = QString(openVpnProc.readAll());
|
|
output.replace("\r", "");
|
|
qDebug() << "TapController: openvpn.exe found, version:" << output;
|
|
return true;
|
|
}
|
|
|
|
QString TapController::getTapInstallPath()
|
|
{
|
|
return getTapDriverDir() + "\\tapinstall.exe";
|
|
}
|
|
|
|
QString TapController::getOpenVpnPath()
|
|
{
|
|
return qApp->applicationDirPath() + "\\openvpn\\openvpn.exe";
|
|
}
|
|
|
|
QString TapController::getTapDriverDir()
|
|
{
|
|
if (oldDriversRequired()) {
|
|
return qApp->applicationDirPath() + "\\tap\\windows_7";
|
|
}
|
|
else {
|
|
return qApp->applicationDirPath() + "\\tap\\windows_10";
|
|
}
|
|
}
|
|
|
|
bool TapController::removeDriver(const QString& tapInstanceId)
|
|
{
|
|
/// remove tap by instance id
|
|
{
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "remove" << QString("@") + tapInstanceId);
|
|
if(!tapInstallProc.waitForStarted()) return false;
|
|
|
|
tapInstallProc.waitForFinished();
|
|
QString output = QString( tapInstallProc.readAll() );
|
|
if (output.contains("were removed")) {
|
|
qDebug() << "TAP device" << tapInstanceId << "successfully removed";
|
|
return true;
|
|
}
|
|
else {
|
|
qDebug() << "Unable to remove TAP device" << tapInstanceId;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TapController::oldDriversRequired()
|
|
{
|
|
if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::Windows7) return true;
|
|
if (QSysInfo::prettyProductName().contains("Server 2008")) return true;
|
|
if (QSysInfo::prettyProductName().contains("Server 2012")) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool TapController::restartTapService()
|
|
{
|
|
{
|
|
QProcess tapRestartroc;
|
|
tapRestartroc.start("net", QStringList() << "stop" << "TapiSrv");
|
|
if(!tapRestartroc.waitForStarted()) return false;
|
|
tapRestartroc.waitForFinished();
|
|
}
|
|
|
|
{
|
|
QProcess tapRestartroc;
|
|
tapRestartroc.start("net", QStringList() << "start" << "TapiSrv");
|
|
if(!tapRestartroc.waitForStarted()) return false;
|
|
tapRestartroc.waitForFinished();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TapController::setupDriver()
|
|
{
|
|
if (oldDriversRequired()) {
|
|
setupDriverCertificate();
|
|
}
|
|
|
|
QStringList tapList = getTapList();
|
|
for (QString tap : tapList) {
|
|
if (! checkDriver(tap)) removeDriver(tap);
|
|
}
|
|
tapList = getTapList();
|
|
if (! tapList.isEmpty()) {
|
|
qDebug() << "TapController: setupDriver :::: Found drivers count" << tapList.size();
|
|
return true;
|
|
}
|
|
|
|
/// else try to install driver
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start(getTapInstallPath(), QStringList() << "install" << getTapDriverDir() + "\\OemVista.inf" << "tap0901");
|
|
bool ok = tapInstallProc.waitForStarted();
|
|
if (!ok) {
|
|
qDebug() << "TapController: setupDriver failer to start tapInstallProc" << tapInstallProc.errorString();
|
|
return false;
|
|
}
|
|
|
|
|
|
tapInstallProc.waitForFinished();
|
|
qDebug() << "TapController: setupDriver args" << tapInstallProc.arguments().join(" ");
|
|
qDebug() << "TapController: setupDriver output" << tapInstallProc.readAll();
|
|
|
|
/// check again
|
|
tapList = getTapList();
|
|
for (QString tap : tapList) {
|
|
if (! checkDriver(tap)) removeDriver(tap);
|
|
}
|
|
tapList = getTapList();
|
|
if (!tapList.isEmpty()) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
bool TapController::setupDriverCertificate()
|
|
{
|
|
QString cert = getTapDriverDir() + "\\OpenVPN.cer";
|
|
QProcess tapInstallProc;
|
|
tapInstallProc.start("certutil" , QStringList() << "-addstore" << "-f" << "trustedpublisher" << cert);
|
|
|
|
tapInstallProc.waitForFinished();
|
|
|
|
QString certOutput = QString(tapInstallProc.readAll());
|
|
qDebug() << "TapController: OpenVPN certificate installed:" << certOutput;
|
|
return true;
|
|
}
|
|
|