diff --git a/src/ioslaves/file/CMakeLists.txt b/src/ioslaves/file/CMakeLists.txt --- a/src/ioslaves/file/CMakeLists.txt +++ b/src/ioslaves/file/CMakeLists.txt @@ -24,7 +24,7 @@ target_link_libraries(kio_file KF5::KIOCore KF5::I18n) if(UNIX) - target_link_libraries(kio_file Qt5::Network) + target_link_libraries(kio_file Qt5::Network KF5::Auth) endif() if (HAVE_VOLMGT AND CMAKE_SYSTEM_NAME MATCHES SunOS) @@ -38,3 +38,7 @@ set_target_properties(kio_file PROPERTIES OUTPUT_NAME "file") set_target_properties(kio_file PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/kio") install(TARGETS kio_file DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/kio) + +if (UNIX) + add_subdirectory(kauth) +endif() diff --git a/src/ioslaves/file/file_p.h b/src/ioslaves/file/file_p.h new file mode 100644 --- /dev/null +++ b/src/ioslaves/file/file_p.h @@ -0,0 +1,37 @@ +/*** + Copyright (C) 2017 by Chinmoy Ranjan Pradhan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +***/ + +#ifndef FILE_P_H +#define FILE_P_H + +enum ActionType { + CHMOD = 1, + CHOWN, + DEL, + MKDIR, + OPEN, + OPENDIR, + RENAME, + RMDIR, + SYMLINK, + UTIME, +}; + +#endif diff --git a/src/ioslaves/file/kauth/CMakeLists.txt b/src/ioslaves/file/kauth/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/ioslaves/file/kauth/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(file_helper filehelper.cpp fdsender.cpp) +target_link_libraries(file_helper Qt5::Network KF5::Auth KF5::I18n KF5::KIOCore) + +install(TARGETS file_helper DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) +kauth_install_helper_files(file_helper org.kde.kio.file root) +kauth_install_actions(org.kde.kio.file file.actions) diff --git a/src/ioslaves/file/kauth/file.actions b/src/ioslaves/file/kauth/file.actions new file mode 100644 --- /dev/null +++ b/src/ioslaves/file/kauth/file.actions @@ -0,0 +1,5 @@ +[org.kde.kio.file.exec] +Name=Execute action as root. +Description=Root privileges are required to complete the action. +Policy=auth_admin +Persistence=session diff --git a/src/ioslaves/file/kauth/filehelper.h b/src/ioslaves/file/kauth/filehelper.h new file mode 100644 --- /dev/null +++ b/src/ioslaves/file/kauth/filehelper.h @@ -0,0 +1,44 @@ +/*** + Copyright (C) 2017 by Chinmoy Ranjan Pradhan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +***/ + + +#ifndef FILEHELPER_H +#define FILEHELPER_H + +#include + +using namespace KAuth; + +/** + * This KAuth helper is responsible for performing file operations with + * root privileges. + */ +class FileHelper : public QObject +{ + Q_OBJECT + +public Q_SLOTS: + /** + * Execute action with root privileges. + **/ + ActionReply exec(const QVariantMap &args); +}; + +#endif diff --git a/src/ioslaves/file/kauth/filehelper.cpp b/src/ioslaves/file/kauth/filehelper.cpp new file mode 100644 --- /dev/null +++ b/src/ioslaves/file/kauth/filehelper.cpp @@ -0,0 +1,139 @@ +/*** + Copyright (C) 2017 by Chinmoy Ranjan Pradhan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +***/ + +#include +#include +#include +#include +#include + +#include "filehelper.h" +#include "fdsender.h" +#include "../file_p.h" + +static bool sendFileDescriptor(int fd, const char *socketPath) +{ + FdSender fdSender(socketPath); + if (fdSender.isConnected() && fdSender.sendFileDescriptor(fd)) { + return true; + } + return false; +} + +ActionReply FileHelper::exec(const QVariantMap &args) +{ + ActionReply reply; + QByteArray data = args["arguments"].toByteArray(); + QDataStream in(data); + int action; + QVariant arg1, arg2, arg3, arg4; + in >> action >> arg1 >> arg2 >> arg3 >> arg4; + + // the path of an existing or a new file/dir upon which the method will operate + const QByteArray path = arg1.toByteArray(); + + switch(action) { + case CHMOD: { + int mode = arg2.toInt(); + if (chmod(path.data(), mode) == 0) { + return reply; + } + break; + } + case CHOWN: { + int uid = arg2.toInt(); + int gid = arg3.toInt(); + if (chown(path.data(), uid, gid) == 0) { + return reply; + } + break; + } + case DEL: { + if (unlink(path.data()) == 0) { + return reply; + } + break; + } + case MKDIR: { + if (mkdir(path.data(), 0777) == 0) { + return reply; + } + break; + } + case OPEN: { + int oflags = arg2.toInt(); + int mode = arg3.toInt(); + int fd = open(path.data(), oflags, mode); + bool success = (fd != -1) && sendFileDescriptor(fd, arg4.toByteArray().constData()); + close(fd); + if (success) { + return reply; + } + break; + } + case OPENDIR: { + DIR *dp = opendir(path.data()); + bool success = false; + if (dp) { + int fd = dirfd(dp); + success = (fd != -1) && sendFileDescriptor(fd, arg4.toByteArray().constData()); + closedir(dp); + if (success) { + return reply; + } + } + break; + } + case RENAME: { + const QByteArray newName = arg2.toByteArray(); + if (rename(path.data(), newName.data()) == 0) { + return reply; + } + break; + } + case RMDIR: { + if (rmdir(path.data()) == 0) { + return reply; + } + break; + } + case SYMLINK: { + const QByteArray target = arg2.toByteArray(); + if (symlink(target.data(), path.data()) == 0) { + return reply; + } + break; + } + case UTIME: { + utimbuf ut; + ut.actime = arg2.toULongLong(); + ut.modtime = arg3.toULongLong(); + if (utime(path.data(), &ut) == 0) { + return reply; + } + break; + } + }; + + reply.setError(errno ? errno : -1); + return reply; +} + +KAUTH_HELPER_MAIN("org.kde.kio.file", FileHelper)