--- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ set(KCM_QUF_VERSION "${KCM_QUF_VERSION_M find_package(ECM 0.0.11 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake/modules) +set(CMAKE_CXX_STANDARD_LIBRARIES -lcryptsetup) + include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings) --- a/src/helper/helper.cpp +++ b/src/helper/helper.cpp @@ -19,26 +19,66 @@ #include "helper.h" #include +#include /** */ ActionReply Helper::format(QVariantMap args) { - + ActionReply reply = ActionReply::SuccessReply(); - - + // Is mounted ?? if( args["mounted"].toBool() ){ qDebug() << "Umounting device : " << args["device"].toString() ; - + if(QProcess::execute("umount", QStringList() << args["device"].toString() ) != 0){ reply = ActionReply::HelperErrorReply(); reply.addData("errorDescription", i18n("umount failed")); return reply; } } + + if (args["makecrypt"].toBool()) { + + int retval; + QByteArray ba; + QString passwd = args["passwd"].toString(); + + struct crypt_device *cd; + struct crypt_params_luks1 params; + + ba = args["device"].toString().toLocal8Bit(); + + retval = crypt_init(&cd, ba.data()); + + if (retval < 0) + goto cleanup; + + params.hash = "sha1"; + params.data_alignment = 0; + params.data_device = nullptr; + + retval = crypt_format(cd, CRYPT_LUKS1, "aes", "xts-plain64", nullptr, nullptr, 256 / 8, ¶ms); + + if (retval < 0) + goto cleanup; + + ba = passwd.toLocal8Bit(); + + retval = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, nullptr, 0, ba.data(), ba.size()); + + if (retval < 0) + goto cleanup; + + return reply; + + cleanup: + reply = ActionReply::HelperErrorReply(); + return reply; + + } QStringList arguments; arguments.append("-c"); @@ -72,7 +112,7 @@ ActionReply Helper::format(QVariantMap a } return reply; -} +} /** --- a/src/window.cpp +++ b/src/window.cpp @@ -34,13 +34,23 @@ Window::Window(DeviceList& dl, QWidget * QWidget *w = new QWidget(this); ui->setupUi(w); setCentralWidget(w); - + + QPalette palette = ui->errLabel->palette(); + palette.setColor(ui->errLabel->foregroundRole(), Qt::red); + ui->errLabel->setPalette(palette); + + ui->passwdLabel->setText(i18n("Input password:")); + this->busy = false; + ui->passwdEdit->setVisible(false); + ui->passwdEdit->setEchoMode(QLineEdit::Password); + ui->passwdLabel->setVisible(false); + deviseUnlocked = false; /* Device slot */ connect(&devList, SIGNAL(refreshDevices(USBDevice, bool)), this, SLOT(refreshListDevices(USBDevice, bool))); devList.initOperation(); - + /* GUI slots */ connect(ui->cb_devices, SIGNAL(activated(QString)), this, SLOT(newDeviceProperties(QString))); @@ -53,6 +63,10 @@ Window::Window(DeviceList& dl, QWidget * ui->cb_filesystem->addItem("f2fs"); ui->cb_filesystem->addItem("exfat"); + ui->selectCrypt->setText(QString(i18n("Encrypt"))); + + connect(ui->selectCrypt, SIGNAL(stateChanged(int)), this, SLOT(selectEncrypt(int))); + // connect(ui->pushButton, SIGNAL(clicked(bool), this, SLOT()); Action *formatAction = new Action("org.kde.auth.quf.format"); formatAction->setHelperId("org.kde.auth.quf"); @@ -90,23 +104,68 @@ QString Window::escapeLabel(const QStrin */ void Window::performAction(KAuth::Action k_action) { + KAuth::Action *action = &k_action; Device actual = getCurrentDevice(); + bool makeCrypt = ui->selectCrypt->isChecked(); + + ExecuteJob *reply; + if(!actual.as()->device().contains(QRegExp("([0-9])$"))){ qWarning() << "WARNING: It is needed to create a partition"; QMessageBox::warning(this, i18n("Warning"), i18n("It is needed to create a partition"), QMessageBox::Ok); return; } - + + QString cryptoPass = ui->passwdEdit->text(); + + ui->errLabel->clear(); + ui->passwdEdit->clear(); + + disableGUI(); + // Obtener argumentos para el formato QString command = ""; QStringList args; QString filesystem = ui->cb_filesystem->currentText(); QString label = ui->label_device->text().trimmed(); QString dirDev = ui->cb_devices->currentText(); - + + QVariantMap map; + + if ( (makeCrypt) & (cryptoPass.isEmpty()) ) { + ui->errLabel->setText(i18n("Crypto password could not is empty!")); + goto cleanup; + } + + lockDevice(); + + if (makeCrypt) { + + map["makecrypt"] = makeCrypt; + map["passwd"] = cryptoPass; + map["mounted"] = actual.as()->isAccessible(); + map["device"] = dirDev; + + qDebug() << "Creating crypto LUKS system..."; + + action->setArguments(map); + reply = startFormat(action, QString(i18n("Device encryption..."))); + + if (reply->error()) + goto cleanup; + + dirDev = unlockDevice(cryptoPass); + + if (!deviseUnlocked) { + ui->errLabel->setText(QString(i18n("Unlock device error..."))); + goto cleanup; + } + + } + if(filesystem == QString("ntfs")){ qDebug() << "**** FORMATTING AS NTFS"; @@ -192,49 +251,124 @@ void Window::performAction(KAuth::Action command = "/sbin/mke2fs"; - } + } else{ qDebug() << "ERROR: Unsupported filesystem = " << filesystem; this->statusBar()->showMessage( i18n("Failed : Unsupported filesystem %1", filesystem) ); - return; + goto cleanup; } - + qDebug() << "EXEC COMMAND : " << command << ", ARGS: " << args; - - QVariantMap map; + + map.clear(); + map["command"] = command; map["args"] = args; map["mounted"] = actual.as()->isAccessible(); map["device"] = dirDev; + action->setArguments(map); - - this->statusBar()->showMessage(i18n("Wait a moment ...")); - - this->busy = true; - this->disableGUI(); - action->setTimeout(1000*60*2.1); - ExecuteJob *reply = action->execute(); - this->busy = false; - this->enableGUI(); - reply->exec(); - - //Syncronous - if (reply->error()){ - //if (reply.type() == ActionReply::KAuthError) { - this->statusBar()->showMessage(i18n("%1, %2", reply->error(), reply->errorString())); - QMessageBox::warning(this, i18n("Warning"), i18n("Failed: Unable to authenticate/execute the action: %1, %2", reply->error(), reply->errorString())); - // There has been an internal KAuth error - //} else { - // Our helper triggered a custom error - // Act accordingly... - // this->statusBar()->showMessage( i18n("Failed : %1", reply.errorDescription()) ); - //} - } - else { + reply = startFormat(action, QString(i18n("Creating new file system..."))); + + setResult(reply); + +cleanup: + + if (deviseUnlocked) + lockDevice(); + + enableGUI(); + +} + +ExecuteJob* Window::startFormat(KAuth::Action *action, QString message) +{ + this->statusBar()->showMessage(message); + this->busy = true; + + action->setTimeout(1000*60*2.1); + ExecuteJob *reply = action->execute(); + + this->busy = false; + + reply->exec(); + + return reply; +} + +void Window::setResult(ExecuteJob *reply) +{ + if (reply->error()) { + this->statusBar()->showMessage(i18n("%1, %2", reply->error(), reply->errorString())); + QMessageBox::warning(this, i18n("Warning"), i18n("Failed: Unable to authenticate/execute the action: %1, %2", reply->error(), reply->errorString())); + + } else { this->statusBar()->showMessage(i18n("Success")); } +} + +struct UdisksIface +{ + QString dest = "org.freedesktop.UDisks2"; + QString path = "/org/freedesktop/UDisks2/block_devices/"; + QString iface = "org.freedesktop.UDisks2.Encrypted"; + QString meth; +}; + +bool Window::createIface() +{ + QDBusConnection dbusConn = QDBusConnection::systemBus(); + if (!dbusConn.isConnected()) + return false; + + UdisksIface udisks; + + QString dbusPath = udisks.path + ui->cb_devices->currentText().split("/").last(); + + dbusIface = new QDBusInterface(udisks.dest, dbusPath, udisks.iface, dbusConn, this); + if (!dbusIface->isValid()) + return false; + + return true; +} + +void Window::lockDevice() +{ + if (!createIface()) + return; + + UdisksIface udisks; + udisks.meth = "Lock"; + + QList args; + args << QMap(); + + dbusIface->callWithArgumentList(QDBus::AutoDetect, udisks.meth, args); + deviseUnlocked = false; +} + +QString Window::unlockDevice(QString passwd) +{ + if (!createIface()) + return QString(""); + + UdisksIface udisks; + udisks.meth = "Unlock"; + + QList args; + args << passwd << QMap(); + + + QDBusMessage msg = dbusIface->callWithArgumentList(QDBus::AutoDetect, udisks.meth, args); + if (msg.errorMessage().isEmpty()) { + deviseUnlocked = true; + return dbusIface->callWithArgumentList(QDBus::AutoDetect, udisks.meth, args).errorMessage().split(" ").last(); + } + + deviseUnlocked = false; + return QString(""); } /* @@ -298,15 +432,33 @@ void Window::refreshDeviceProperties() newDeviceProperties(str_device); } +void Window::selectEncrypt(int encrypt) +{ + + if (encrypt) { + + setLabel(); + + ui->passwdEdit->setVisible(true); + ui->passwdLabel->setVisible(true); + + } else { + + ui->passwdEdit->setVisible(false); + ui->passwdLabel->setVisible(false); + + } +} + void Window::newDeviceProperties(QString devname) { USBDevice usb = devList.findDeviceFromPath(devname); QString size; size.setNum(usb.getCapacity()); - + deviceFilesystem = usb.getFilesystem(); ui->lb_product->setText( usb.getVendor() ); ui->lb_size->setText( size.append("MB") ); - ui->lb_filesystem->setText( usb.getFilesystem()); + ui->lb_filesystem->setText( deviceFilesystem); // Icon depending of system QLabel *label = ui->label_icon; @@ -324,6 +476,8 @@ void Window::newDeviceProperties(QString } } + + setLabel(); enableGUI(); } @@ -335,6 +489,14 @@ Device Window::getCurrentDevice() return ud.getDevice(); } +void Window::setLabel() +{ + if (deviceFilesystem == LUKSFILESYSTEM) + ui->passwdLabel->setText(QString(i18n("Input your password:"))); + else + ui->passwdLabel->setText(QString(i18n("Input new password:"))); +} + void Window::disableGUI() { ui->widget->setDisabled(true); --- a/src/window.h +++ b/src/window.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "devices.h" #include "usbdevice.h" @@ -57,6 +58,7 @@ public Q_SLOTS: void refreshListDevices(USBDevice, bool); void enableGUI(); void disableGUI(); + void selectEncrypt(int encrypt); /** * Se ejecuta cuando se autoriza una action @@ -70,7 +72,17 @@ private: Device getCurrentDevice(); QString escapeLabel(const QString label); void actionResult(KJob *kjob); - bool busy; + bool busy; + void lockDevice(); + QString unlockDevice(QString passwd); + bool createIface(); + QDBusInterface *dbusIface; + bool deviseUnlocked; + QString deviceFilesystem; + const QString LUKSFILESYSTEM = QString("crypto_LUKS"); + ExecuteJob* startFormat(KAuth::Action *action, QString message); + void setResult(ExecuteJob *reply); + void setLabel(); }; --- a/src/window.ui +++ b/src/window.ui @@ -7,7 +7,7 @@ 0 0 327 - 272 + 297 @@ -101,7 +101,7 @@ - + true @@ -111,7 +111,7 @@ - + true @@ -300,10 +300,34 @@ + + + + + + + Input password: + + + + + + + encrypt device + + + + + + + + + + Qt::Vertical