/*************************************************************************** * This file is part of netctl-gui * * * * netctl-gui is free software: you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * netctl-gui is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with netctl-gui. If not, see http://www.gnu.org/licenses/ * ***************************************************************************/ /** * @file wpasupinteract.cpp * Source code of netctlgui library * @author Evgeniy Alekseev * @copyright GPLv3 * @bug https://github.com/arcan1s/netctl-gui/issues */ #include #include #include #include #include /** * @class WpaSup */ /** * @fn WpaSup */ WpaSup::WpaSup(const bool debugCmd, const QMap settings) : debug(debugCmd) { netctlCommand = new Netctl(debug, settings); netctlProfile = new NetctlProfile(debug, settings); if (settings.contains(QString("CTRL_DIR"))) ctrlDir = settings[QString("CTRL_DIR")]; if (settings.contains(QString("CTRL_GROUP"))) ctrlGroup = settings[QString("CTRL_GROUP")]; if (settings.contains(QString("PID_FILE"))) pidFile = settings[QString("PID_FILE")]; if (settings.contains(QString("SUDO_PATH"))) sudoCommand = settings[QString("SUDO_PATH")]; if (settings.contains(QString("WPACLI_PATH"))) wpaCliPath = settings[QString("WPACLI_PATH")]; if (settings.contains(QString("WPA_DRIVERS"))) wpaDrivers = settings[QString("WPA_DRIVERS")]; if (settings.contains(QString("WPASUP_PATH"))) wpaSupPath = settings[QString("WPASUP_PATH")]; if (settings.contains(QString("FORCE_SUDO"))) useSuid = (settings[QString("FORCE_SUDO")] != QString("true")); if (useSuid) sudoCommand = QString(""); } /** * @fn ~WpaSup */ WpaSup::~WpaSup() { if (debug) qDebug() << PDEBUG; if (netctlCommand != nullptr) delete netctlCommand; if (netctlProfile != nullptr) delete netctlProfile; } // general information /** * @fn existentProfile */ QString WpaSup::existentProfile(const QString essid) { if (debug) qDebug() << PDEBUG; if (debug) qDebug() << PDEBUG << ":" << "ESSID" << essid; if (netctlCommand == nullptr) { if (debug) qDebug() << PDEBUG << ":" << "Could not find library"; return QString(); } if (netctlProfile == nullptr) { if (debug) qDebug() << PDEBUG << ":" << "Could not find library"; return QString(); } QString profileFile = QString(""); QList profileList = netctlCommand->getProfileList(); for (int i=0; igetValueFromProfile(profileList[i].name, QString("ESSID"))) profileFile = profileList[i].name; return profileFile; } /** * @fn getRecommendedConfiguration */ QMap WpaSup::getRecommendedConfiguration() { QMap settings; int size = 99; TaskResult process; QStringList recommended; // ctrl directory // nothing to do settings[QString("CTRL_DIR")] = QString("/run/wpa_supplicant"); // ctrl group // check group list and find out 'network', 'users', 'root' settings[QString("CTRL_GROUP")] = QString(""); gid_t gtpList[99]; int grpSize = getgroups(size, gtpList); recommended.clear(); recommended.append("network"); recommended.append("users"); recommended.append("root"); for (int i=0; igr_name)) { settings[QString("CTRL_GROUP")] = recommended[i]; break; } if (!settings[QString("CTRL_GROUP")].isEmpty()) break; } // force sudo // find out helper exe settings[QString("FORCE_SUDO")] = QString("true"); recommended.clear(); recommended.append(QString("netctlgui-helper")); recommended.append(QString("netctlgui-helper-suid")); for (int i=0; i profileList = netctlCommand->getProfileList(); for (int i=0; igetValueFromProfile(profileList[i].name, QString("ESSID"))) { profileFile = profileList[i].name; break; } return netctlCommand->isProfileActive(profileFile); } /** * @fn isProfileExists */ bool WpaSup::isProfileExists(const QString essid) { if (debug) qDebug() << PDEBUG; if (debug) qDebug() << PDEBUG << ":" << "ESSID" << essid; if (netctlCommand == nullptr) { if (debug) qDebug() << PDEBUG << ":" << "Could not find library"; return false; } if (netctlProfile == nullptr) { if (debug) qDebug() << PDEBUG << ":" << "Could not find library"; return false; } bool exists = false; QList profileList = netctlCommand->getProfileList(); for (int i=0; igetValueFromProfile(profileList[i].name, QString("ESSID"))) { exists = true; break; } return exists; } /** * @fn current */ netctlWifiInfo WpaSup::current() { if (debug) qDebug() << PDEBUG; if (pidFile.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find PID file"; return netctlWifiInfo(); } QStringList interfaces = netctlCommand->getWirelessInterfaceList(); if (interfaces.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find interfaces"; return netctlWifiInfo(); } QString _pidFile = pidFile; _pidFile.replace(QString("$i"), interfaces[0]); if (debug) qDebug() << PDEBUG << ":" << "PID file" << _pidFile << QFile(_pidFile).exists(); netctlWifiInfo current; if (!QFile(_pidFile).exists()) return current; QStringList rawList = getWpaCliOutput(QString("status")).split(QChar('\n'), QString::SkipEmptyParts); for (int i=0; i= 5000) && (line[1].toInt() < 6000)) current.type = PointType::FiveG; else if ((line[1].toInt() < 5000) && (line[1].toInt() > 2000)) current.type = PointType::TwoG; current.frequencies.append(line[1].toInt()); } else if (line[0] == QString("ssid")) current.name = line[1]; else if (line[0] == QString("key_mgmt")) { QString security = line[1]; if (security.contains(QString("WPA2"))) security = QString("WPA2"); else if (security.contains(QString("WPA"))) security = QString("WPA"); else if (security.contains(QString("WEP"))) security = QString("WEP"); else security = QString("none"); current.security = security; } } current.signal = 0; // status current.active = true; QList profiles = netctlCommand->getProfileList(); for (int j=0; j WpaSup::scanWifi() { if (debug) qDebug() << PDEBUG; if (pidFile.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find PID file"; return QList(); } QStringList interfaces = netctlCommand->getWirelessInterfaceList(); if (interfaces.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find interfaces"; return QList(); } QString _pidFile = pidFile; _pidFile.replace(QString("$i"), interfaces[0]); if (debug) qDebug() << PDEBUG << ":" << "PID file" << _pidFile << QFile(_pidFile).exists(); bool terminateOnExit = (!QFile(_pidFile).exists()); QList scanResults; if (!startWpaSupplicant()) { if (terminateOnExit) stopWpaSupplicant(); return scanResults; } if (!wpaCliCall(QString("scan"))) return scanResults; waitForProcess(3); QStringList rawList = getWpaCliOutput(QString("scan_results")).split(QChar('\n'), QString::SkipEmptyParts); // remove table header rawList.removeFirst(); QStringList names; QList profiles = netctlCommand->getProfileList(); for (int i=0; i"); // append mac and frequency if exists int index = names.indexOf(name); if ((name != QString("")) && (index > -1)) { scanResults[index].frequencies.append(line[1].toInt()); scanResults[index].macs.append(line[0]); if (scanResults[index].signal < line[2].toInt()) scanResults[index].signal = line[2].toInt(); // check type if ((line[1].toInt() >= 5000) && (line[1].toInt() < 6000)) { if (scanResults[index].type == PointType::None) scanResults[index].type = PointType::FiveG; else if (scanResults[index].type == PointType::TwoG) scanResults[index].type = PointType::TwoAndFiveG; } else if ((line[1].toInt() < 5000) && (line[1].toInt() > 2000)) { if (scanResults[index].type == PointType::None) scanResults[index].type = PointType::TwoG; else if (scanResults[index].type == PointType::FiveG) scanResults[index].type = PointType::TwoAndFiveG; } continue; } // point name netctlWifiInfo wifiPoint; wifiPoint.name = name; // profile status netctlProfileInfo profile; profile.name = QString(""); profile.active = false; for (int j=0; j= 5000) && (line[1].toInt() < 6000)) { wifiPoint.type = PointType::FiveG; } else if ((line[1].toInt() < 5000) && (line[1].toInt() > 2000)) { wifiPoint.type = PointType::TwoG; } // point signal wifiPoint.signal = line[2].toInt(); // point security QString security = line[3]; if (security.contains(QString("WPA2"))) security = QString("WPA2"); else if (security.contains(QString("WPA"))) security = QString("WPA"); else if (security.contains(QString("WEP"))) security = QString("WEP"); else security = QString("none"); wifiPoint.security = security; // append names.append(name); scanResults.append(wifiPoint); } if (terminateOnExit) stopWpaSupplicant(); return scanResults; } /** * @fn startWpaSupplicant */ bool WpaSup::startWpaSupplicant() { if (debug) qDebug() << PDEBUG; if (ctrlDir.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find directory"; return false; } if (ctrlGroup.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find group"; return false; } if (pidFile.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find PID file"; return false; } if (wpaDrivers.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find drivers"; return false; } if (wpaSupPath.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find wpa_supplicant"; return false; } if (netctlCommand == nullptr) { if (debug) qDebug() << PDEBUG << ":" << "Could not find library"; return false; } QStringList interfaces = netctlCommand->getWirelessInterfaceList(); if (interfaces.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find interfaces"; return false; } QString _pidFile = pidFile; _pidFile.replace(QString("$i"), interfaces[0]); if (debug) qDebug() << PDEBUG << ":" << "PID file" << _pidFile << QFile(_pidFile).exists(); if (QFile(_pidFile).exists()) return (QFileInfo(ctrlDir).group() == ctrlGroup); QString cmd = QString("%1 %2 -B -P \"%3\" -i %4 -D %5 -C \"DIR=%6 GROUP=%7\"") .arg(sudoCommand).arg(wpaSupPath).arg(_pidFile).arg(interfaces[0]) .arg(wpaDrivers).arg(ctrlDir).arg(ctrlGroup); if (debug) qDebug() << PDEBUG << ":" << "Run cmd" << cmd; TaskResult process = runTask(cmd, useSuid); waitForProcess(1); if (debug) qDebug() << PDEBUG << ":" << "Cmd returns" << process.exitCode; if (process.exitCode != 0) if (debug) qDebug() << PDEBUG << ":" << "Error" << process.error; return (process.exitCode == 0); } /** * @fn stopWpaSupplicant */ bool WpaSup::stopWpaSupplicant() { if (debug) qDebug() << PDEBUG; return wpaCliCall(QString("terminate")); } // functions /** * @fn getWpaCliOutput */ QString WpaSup::getWpaCliOutput(const QString commandLine) { if (debug) qDebug() << PDEBUG; if (debug) qDebug() << PDEBUG << ":" << "Command" << commandLine; if (ctrlDir.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find directory"; return QString(); } if (wpaCliPath.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find wpa_cli"; return QString(); } QStringList interfaces = netctlCommand->getWirelessInterfaceList(); if (interfaces.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find interfaces"; return false; } QString cmd = QString("%1 -i %2 -p %3 %4").arg(wpaCliPath).arg(interfaces[0]).arg(ctrlDir).arg(commandLine); if (debug) qDebug() << PDEBUG << ":" << "Run cmd" << cmd; TaskResult process = runTask(cmd); if (debug) qDebug() << PDEBUG << ":" << "Cmd returns" << process.exitCode; if (process.exitCode != 0) if (debug) qDebug() << PDEBUG << ":" << "Error" << process.error; return process.output; } /** * @fn waitForProcess */ bool WpaSup::waitForProcess(const int sec) { if (debug) qDebug() << PDEBUG; if (debug) qDebug() << PDEBUG << ":" << "Interval" << sec; QString cmd = QString("sleep %1").arg(sec); runTask(cmd); return true; } /** * @fn wpaCliCall */ bool WpaSup::wpaCliCall(const QString commandLine) { if (debug) qDebug() << PDEBUG; if (debug) qDebug() << PDEBUG << ":" << "Command" << commandLine; if (ctrlDir.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find directory"; return false; } if (wpaCliPath.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find wpa_cli"; return false; } QStringList interfaces = netctlCommand->getWirelessInterfaceList(); if (interfaces.isEmpty()) { if (debug) qDebug() << PDEBUG << ":" << "Could not find interfaces"; return false; } QString cmd = QString("%1 -i %2 -p %3 %4").arg(wpaCliPath).arg(interfaces[0]).arg(ctrlDir).arg(commandLine); if (debug) qDebug() << PDEBUG << ":" << "Run cmd" << cmd; TaskResult process = runTask(cmd); waitForProcess(1); if (debug) qDebug() << PDEBUG << ":" << "Cmd returns" << process.exitCode; if (process.exitCode != 0) if (debug) qDebug() << PDEBUG << ":" << "Error" << process.error; return (process.exitCode == 0); }