From fdd7fbae926821be7d5229d5cba04396e6f00f99 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 17 Jul 2009 19:00:40 +0200 Subject: =?UTF-8?q?UserBackendHome=20hinzugef=C3=BCgt=20Modul=20zur=20Erst?= =?UTF-8?q?ellung=20von=20Home-Verzeichnissen=20implementert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- src/mad-server.conf | 5 + src/mad-server.cpp | 1 + src/modules/CMakeLists.txt | 1 + src/modules/UserBackendHome/CMakeLists.txt | 8 + src/modules/UserBackendHome/Module.cpp | 28 ++++ src/modules/UserBackendHome/Module.h | 52 +++++++ src/modules/UserBackendHome/UserBackendHome.cpp | 195 ++++++++++++++++++++++++ src/modules/UserBackendHome/UserBackendHome.h | 69 +++++++++ 9 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 src/modules/UserBackendHome/CMakeLists.txt create mode 100644 src/modules/UserBackendHome/Module.cpp create mode 100644 src/modules/UserBackendHome/Module.h create mode 100644 src/modules/UserBackendHome/UserBackendHome.cpp create mode 100644 src/modules/UserBackendHome/UserBackendHome.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d884224..8da14e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ find_package(DL REQUIRED) find_package(Readline REQUIRED) #find_package(KRB5 REQUIRED gssapi) find_package(OpenSSL REQUIRED) -find_package(Boost REQUIRED date_time regex signals system thread) +find_package(Boost REQUIRED date_time filesystem regex signals system thread) find_package(MySQL) configure_file(${MAD_SOURCE_DIR}/config.h.in ${MAD_BINARY_DIR}/config.h) diff --git a/src/mad-server.conf b/src/mad-server.conf index 76533cf..41aa298 100644 --- a/src/mad-server.conf +++ b/src/mad-server.conf @@ -33,6 +33,11 @@ UserBackendMysql { } } +UserBackendHome { + HomeDir "/tmp/home" + Skeleton "/tmp/skel" +} + Daemon test { IpAddress 127.0.0.1 } diff --git a/src/mad-server.cpp b/src/mad-server.cpp index 870567f..1749ba2 100644 --- a/src/mad-server.cpp +++ b/src/mad-server.cpp @@ -33,6 +33,7 @@ int main() { application.getModuleManager()->loadModule("SystemBackendProc"); application.getModuleManager()->loadModule("UserBackendMysql"); + application.getModuleManager()->loadModule("UserBackendHome"); application.getConfigManager()->loadFile("mad-server.conf"); application.getConfigManager()->finish(); diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index fb9aac0..774b4eb 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -34,6 +34,7 @@ endmacro(mad_module_libraries) add_subdirectory(FileLogger) add_subdirectory(SystemBackendPosix) add_subdirectory(SystemBackendProc) +add_subdirectory(UserBackendHome) if(MYSQL_FOUND) add_subdirectory(UserBackendMysql) diff --git a/src/modules/UserBackendHome/CMakeLists.txt b/src/modules/UserBackendHome/CMakeLists.txt new file mode 100644 index 0000000..9d053f3 --- /dev/null +++ b/src/modules/UserBackendHome/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${INCLUDES}) + +mad_module(UserBackendHome + Module.cpp Module.h + UserBackendHome.cpp UserBackendHome.h +) + +mad_module_libraries(UserBackendHome) \ No newline at end of file diff --git a/src/modules/UserBackendHome/Module.cpp b/src/modules/UserBackendHome/Module.cpp new file mode 100644 index 0000000..b6a1052 --- /dev/null +++ b/src/modules/UserBackendHome/Module.cpp @@ -0,0 +1,28 @@ +/* + * Module.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 program. If not, see . + */ + +#include "Module.h" + +extern "C" { + +Mad::Common::Module* UserBackendHome_create(Mad::Common::Application *application) { + return new Mad::Modules::UserBackendHome::Module(application); +} + +} diff --git a/src/modules/UserBackendHome/Module.h b/src/modules/UserBackendHome/Module.h new file mode 100644 index 0000000..da384bc --- /dev/null +++ b/src/modules/UserBackendHome/Module.h @@ -0,0 +1,52 @@ +/* + * Module.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 program. If not, see . + */ + +#ifndef MAD_MODULES_USERBACKENDHOME_MODULE_H_ +#define MAD_MODULES_USERBACKENDHOME_MODULE_H_ + +#include "UserBackendHome.h" + +#include +#include + +namespace Mad { +namespace Modules { +namespace UserBackendHome { + +class Module : public Common::Module { + private: + Common::Application *application; + + boost::shared_ptr backend; + + public: + Module(Common::Application *application0) : application(application0), backend(new UserBackendHome(application)) { + application->getUserManager()->registerBackend(backend); + } + + virtual ~Module() { + application->getUserManager()->unregisterBackend(backend); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERBACKENDHOME_MODULE_H_ */ diff --git a/src/modules/UserBackendHome/UserBackendHome.cpp b/src/modules/UserBackendHome/UserBackendHome.cpp new file mode 100644 index 0000000..d524a52 --- /dev/null +++ b/src/modules/UserBackendHome/UserBackendHome.cpp @@ -0,0 +1,195 @@ +/* + * UserBackendHome.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 program. If not, see . + */ + +#include "UserBackendHome.h" +#include +#include + +#include + +#include +#include +#include + +namespace Mad { +namespace Modules { +namespace UserBackendHome { + +bool UserBackendHome::handleConfigEntry(const Core::ConfigEntry &entry, bool handled) { + if(handled) + return false; + + if(entry[0].getKey().matches("UserBackendHome")) { + if(entry[1].getKey().matches("Skeleton")) { + if(entry[2].empty()) + skeleton = entry[1][0]; + } + else if(entry[1].getKey().matches("HomeDir")) { + if(entry[2].empty()) + homeDir = entry[1][0]; + } + else if(!entry[1].empty()) + return false; + + return true; + } + + return false; +} + +void UserBackendHome::setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink) { + if((isSymlink ? lchown : chown)(dest.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + struct stat st; + if((isSymlink ? lstat : stat)(source.c_str(), &st) == 0) { + if((isSymlink ? lchmod : chmod)(dest.c_str(), st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != 0) { + // TODO Error + } + } +} + +void migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink) { + struct stat st; + if((isSymlink ? lstat : stat)(path.c_str(), &st) != 0) { + // TODO Error + return; + } + + uid_t uid = -1; + gid_t gid = -1; + + if(st.st_uid == oldUserInfo.getUid()) + uid = (uid_t)userInfo.getUid(); + + if(st.st_gid == oldUserInfo.getGid()) + gid = (gid_t)userInfo.getGid(); + + if(uid != (uid_t)-1 || gid != (gid_t)-1) { + if((isSymlink ? lchown : chown)(path.c_str(), uid, gid) != 0) { + // TODO Error + } + } +} + +void UserBackendHome::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + boost::filesystem::create_directories(path); + + std::string nativePath = path.directory_string(); + if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + boost::filesystem::path skeletonPath(skeleton); + if(!boost::filesystem::is_directory(skeletonPath)) + return; + + boost::filesystem::path oldPath = boost::filesystem::current_path(); + boost::filesystem::current_path(skeletonPath); + + boost::filesystem::recursive_directory_iterator end; + + for(boost::filesystem::recursive_directory_iterator it("."); it != end; ++it) { + boost::filesystem::path source = it->path(); + boost::filesystem::path dest = path / source; + + try { + if(boost::filesystem::is_symlink(it->symlink_status())) { + it.no_push(); + + std::string sourceStr = source.file_string(); + + char link[PATH_MAX]; + int ret = ::readlink(sourceStr.c_str(), link, PATH_MAX); + if(ret <= 0) + continue; + + boost::filesystem::create_symlink(boost::filesystem::path(std::string(link, ret)), dest); + setOwnerAndCopyMode(sourceStr, dest.file_string(), userInfo, true); + } + else if(boost::filesystem::is_directory(it->status())) { + boost::filesystem::create_directory(dest); + setOwnerAndCopyMode(source.directory_string(), dest.directory_string(), userInfo, false); + } + else { + boost::filesystem::copy_file(source, dest); + setOwnerAndCopyMode(source.file_string(), dest.file_string(), userInfo, false); + } + } + catch(...) {} + } + + boost::filesystem::current_path(oldPath); +} + +void UserBackendHome::updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path oldPath(homeDir); + oldPath /= oldUserInfo.getUsername(); + + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + if(oldPath != path) { + try { + boost::filesystem::rename(oldPath, path); + } + catch(...) { + return; + } + } + + if(oldUserInfo.getUid() == userInfo.getUid() && oldUserInfo.getGid() == userInfo.getGid()) + return; + + std::string nativePath = path.directory_string(); + if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + boost::filesystem::recursive_directory_iterator end; + + for(boost::filesystem::recursive_directory_iterator it(path); it != end; ++it) { + if(boost::filesystem::is_symlink(it->symlink_status())) { + it.no_push(); + + migrateOwner(it->path().file_string(), oldUserInfo, userInfo, true); + } + else if(boost::filesystem::is_directory(it->status())) { + migrateOwner(it->path().directory_string(), oldUserInfo, userInfo, false); + } + else { + migrateOwner(it->path().file_string(), oldUserInfo, userInfo, false); + } + } +} + +void UserBackendHome::deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + boost::filesystem::remove_all(path); +} + +} +} +} diff --git a/src/modules/UserBackendHome/UserBackendHome.h b/src/modules/UserBackendHome/UserBackendHome.h new file mode 100644 index 0000000..1e2b0a3 --- /dev/null +++ b/src/modules/UserBackendHome/UserBackendHome.h @@ -0,0 +1,69 @@ +/* + * UserBackendMysql.h + * + * Copyright (C) 2008 Matthias Schiffer + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 program. If not, see . + */ + +#ifndef MAD_MODULES_USERBACKENDHOME_USERBACKENDHOME_H_ +#define MAD_MODULES_USERBACKENDHOME_USERBACKENDHOME_H_ + +#include +#include + +#include +#include + +#include + +namespace Mad { +namespace Modules { +namespace UserBackendHome { + +class UserBackendHome : public Common::UserConfigBackend, private Core::Configurable, private boost::noncopyable { + private: + Common::Application *application; + + std::string skeleton; + std::string homeDir; + + boost::mutex mutex; + + void setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink); + + void migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink); + + protected: + virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool handled); + + virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); + virtual void updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception); + virtual void deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception); + + public: + UserBackendHome(Common::Application *application0) : application(application0), homeDir("/home") { + application->getConfigManager()->registerConfigurable(this); + } + + virtual ~UserBackendHome() { + application->getConfigManager()->unregisterConfigurable(this); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERBACKENDHOME_USERBACKENDHOME_H_ */ -- cgit v1.2.3