From d7edb4799b63b9bbde25a0d04603476aaf8acd50 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 9 Aug 2009 18:52:17 +0200 Subject: Renamed UserBackendMysql to UserDBBackendMysql and UserBackendHome to UserConfigBackendHome --- src/modules/UserConfigBackendHome/CMakeLists.txt | 8 + src/modules/UserConfigBackendHome/Module.cpp | 28 +++ src/modules/UserConfigBackendHome/Module.h | 52 +++++ .../UserConfigBackendHome.cpp | 213 +++++++++++++++++++++ .../UserConfigBackendHome/UserConfigBackendHome.h | 70 +++++++ 5 files changed, 371 insertions(+) create mode 100644 src/modules/UserConfigBackendHome/CMakeLists.txt create mode 100644 src/modules/UserConfigBackendHome/Module.cpp create mode 100644 src/modules/UserConfigBackendHome/Module.h create mode 100644 src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp create mode 100644 src/modules/UserConfigBackendHome/UserConfigBackendHome.h (limited to 'src/modules/UserConfigBackendHome') diff --git a/src/modules/UserConfigBackendHome/CMakeLists.txt b/src/modules/UserConfigBackendHome/CMakeLists.txt new file mode 100644 index 0000000..4f8e224 --- /dev/null +++ b/src/modules/UserConfigBackendHome/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${INCLUDES}) + +mad_module(UserConfigBackendHome + Module.cpp Module.h + UserConfigBackendHome.cpp UserConfigBackendHome.h +) + +mad_module_libraries(UserConfigBackendHome) \ No newline at end of file diff --git a/src/modules/UserConfigBackendHome/Module.cpp b/src/modules/UserConfigBackendHome/Module.cpp new file mode 100644 index 0000000..cab1b80 --- /dev/null +++ b/src/modules/UserConfigBackendHome/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* UserConfigBackendHome_create(Mad::Common::Application *application) { + return new Mad::Modules::UserConfigBackendHome::Module(application); +} + +} diff --git a/src/modules/UserConfigBackendHome/Module.h b/src/modules/UserConfigBackendHome/Module.h new file mode 100644 index 0000000..1d6322d --- /dev/null +++ b/src/modules/UserConfigBackendHome/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_USERCONFIGBACKENDHOME_MODULE_H_ +#define MAD_MODULES_USERCONFIGBACKENDHOME_MODULE_H_ + +#include "UserConfigBackendHome.h" + +#include +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendHome { + +class Module : public Common::Module { + private: + Common::Application *application; + + boost::shared_ptr backend; + + public: + Module(Common::Application *application0) : application(application0), backend(new UserConfigBackendHome(application)) { + application->getUserManager()->registerBackend(backend); + } + + virtual ~Module() { + application->getUserManager()->unregisterBackend(backend); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERCONFIGBACKENDHOME_MODULE_H_ */ diff --git a/src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp b/src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp new file mode 100644 index 0000000..b68268b --- /dev/null +++ b/src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp @@ -0,0 +1,213 @@ +/* + * UserConfigBackendHome.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 "UserConfigBackendHome.h" +#include +#include + +#include + +#include +#include +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendHome { + +bool UserConfigBackendHome::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(entry[0].getKey().matches("UserManager")) { + 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].getKey().matches("UserDirMode")) { + if(entry[2].empty()) { + if(entry[1][0].empty()) { + dirMode = 0755; + } + else { + char *endptr; + unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 8); + if(*endptr || val > 07777) { + application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: DirMode '%s'", entry[1][0].c_str()); + } + else { + dirMode = val; + } + } + } + } + else if(!entry[1].empty()) + return false; + + return true; + } + + return false; +} + +void UserConfigBackendHome::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 UserConfigBackendHome::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 UserConfigBackendHome::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 + } + + if(chmod(nativePath.c_str(), (mode_t)dirMode)) { + // 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 UserConfigBackendHome::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 UserConfigBackendHome::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/UserConfigBackendHome/UserConfigBackendHome.h b/src/modules/UserConfigBackendHome/UserConfigBackendHome.h new file mode 100644 index 0000000..f115d9e --- /dev/null +++ b/src/modules/UserConfigBackendHome/UserConfigBackendHome.h @@ -0,0 +1,70 @@ +/* + * UserConfigBackendMysql.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_USERCONFIGBACKENDHOME_USERCONFIGBACKENDHOME_H_ +#define MAD_MODULES_USERCONFIGBACKENDHOME_USERCONFIGBACKENDHOME_H_ + +#include +#include + +#include +#include + +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendHome { + +class UserConfigBackendHome : public Common::UserConfigBackend, private Core::Configurable, private boost::noncopyable { + private: + Common::Application *application; + + std::string skeleton; + std::string homeDir; + unsigned long dirMode; + + 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: + UserConfigBackendHome(Common::Application *application0) : application(application0), homeDir("/home"), dirMode(0755) { + application->getConfigManager()->registerConfigurable(this); + } + + virtual ~UserConfigBackendHome() { + application->getConfigManager()->unregisterConfigurable(this); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERCONFIGBACKENDHOME_USERCONFIGBACKENDHOME_H_ */ -- cgit v1.2.3