From 0d1a7cb65b7b0f5ecc8e3cd6fbabdebab7f47f7f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 6 Aug 2009 21:28:41 +0200 Subject: Revised server config format --- config.h.in | 2 + src/Common/UserManager.cpp | 76 +++++++++ src/Common/UserManager.h | 11 +- src/Core/Configurable.h | 2 +- src/Core/Exception.cpp | 2 + src/Net/Listener.h | 2 +- src/Server/ConnectionManager.cpp | 43 +++-- src/Server/ConnectionManager.h | 2 + src/mad-server.conf | 56 ++++--- src/modules/UserBackendHome/UserBackendHome.cpp | 9 +- src/modules/UserBackendMysql/UserBackendMysql.cpp | 188 +++++++++++----------- 11 files changed, 249 insertions(+), 144 deletions(-) diff --git a/config.h.in b/config.h.in index 8d1db02..80e4694 100644 --- a/config.h.in +++ b/config.h.in @@ -1 +1,3 @@ #define MODULE_SUFFIX "${CMAKE_SHARED_MODULE_SUFFIX}" + +#define DEFAULT_PORT 6666 \ No newline at end of file diff --git a/src/Common/UserManager.cpp b/src/Common/UserManager.cpp index 7f50f28..bb4d205 100644 --- a/src/Common/UserManager.cpp +++ b/src/Common/UserManager.cpp @@ -22,9 +22,79 @@ #include "UserCache.h" #include "UserConfigBackend.h" +#include +#include + namespace Mad { namespace Common { +UserManager::UserManager(Application *application0) : application(application0), minUid(1000), maxUid(29999), minGid(1000), maxGid(29999) { + application->getConfigManager()->registerConfigurable(this); +} + +UserManager::~UserManager() { + application->getConfigManager()->unregisterConfigurable(this); +} + +bool UserManager::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(entry[0].getKey().matches("UserManager")) { + if(entry[1].getKey().matches("MinUid")) { + if(entry[2].empty()) { + char *endptr; + unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 10); + if(entry[1][0].empty() || *endptr) { + application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: MinUid '%s'", entry[1][0].c_str()); + } + else { + minUid = val; + } + } + } + else if(entry[1].getKey().matches("MaxUid")) { + if(entry[2].empty()) { + char *endptr; + unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 10); + if(entry[1][0].empty() || *endptr) { + application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: MaxUid '%s'", entry[1][0].c_str()); + } + else { + maxUid = val; + } + } + } + else if(entry[1].getKey().matches("MinGid")) { + if(entry[2].empty()) { + char *endptr; + unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 10); + if(entry[1][0].empty() || *endptr) { + application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: MinGid '%s'", entry[1][0].c_str()); + } + else { + minGid = val; + } + } + } + else if(entry[1].getKey().matches("MaxGid")) { + if(entry[2].empty()) { + char *endptr; + unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 10); + if(entry[1][0].empty() || *endptr) { + application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: MaxGid '%s'", entry[1][0].c_str()); + } + else { + maxGid = val; + } + } + } + else if(!entry[1].empty()) + return false; + + return true; + } + + return false; +} + void UserManager::registerBackend(boost::shared_ptr backend) { boost::lock_guard lock(mutex); @@ -143,6 +213,9 @@ void UserManager::checkUserInfo(const UserInfo &userInfo) throw(Core::Exception) if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); + if(userInfo.getUid() < minUid || userInfo.getUid() > maxUid) + throw Core::Exception(Core::Exception::INVALID_INPUT); + dbBackend->checkUserInfo(userInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { @@ -223,6 +296,9 @@ void UserManager::checkGroupInfo(const GroupInfo &groupInfo) throw(Core::Excepti if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); + if(groupInfo.getGid() < minGid || groupInfo.getGid() > maxGid) + throw Core::Exception(Core::Exception::INVALID_INPUT); + dbBackend->checkGroupInfo(groupInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { diff --git a/src/Common/UserManager.h b/src/Common/UserManager.h index 5eece35..c70894a 100644 --- a/src/Common/UserManager.h +++ b/src/Common/UserManager.h @@ -23,6 +23,7 @@ #include "UserInfo.h" #include "GroupInfo.h" +#include #include #include @@ -39,7 +40,7 @@ class UserConfigBackend; class UserDBBackend; class UserCache; -class UserManager : private boost::noncopyable { +class UserManager : public Core::Configurable, private boost::noncopyable { private: friend class Application; @@ -54,9 +55,15 @@ class UserManager : private boost::noncopyable { boost::shared_ptr dbBackend; + unsigned long minUid, maxUid, minGid, maxGid; + boost::shared_mutex mutex; - UserManager(Application *application0) : application(application0) {} + UserManager(Application *application0); + ~UserManager(); + + protected: + virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/); public: void registerBackend(boost::shared_ptr backend); diff --git a/src/Core/Configurable.h b/src/Core/Configurable.h index 6eb4cd6..c526379 100644 --- a/src/Core/Configurable.h +++ b/src/Core/Configurable.h @@ -37,7 +37,7 @@ class Configurable { Configurable() {} - virtual bool handleConfigEntry(const ConfigEntry&, bool) {return false;} + virtual bool handleConfigEntry(const ConfigEntry& /*entry*/, bool /*handled*/) {return false;} virtual void configFinished() {} }; diff --git a/src/Core/Exception.cpp b/src/Core/Exception.cpp index ba8b114..af39654 100644 --- a/src/Core/Exception.cpp +++ b/src/Core/Exception.cpp @@ -45,6 +45,8 @@ std::string Exception::strerror() const { return ret + "Not implemented"; case NOT_FOUND: return ret + "Not found"; + case INVALID_INPUT: + return ret + "Invalid input"; case INTERNAL_ERRNO: return ret + std::strerror(subCode); case INVALID_ADDRESS: diff --git a/src/Net/Listener.h b/src/Net/Listener.h index 6f81a78..2addafd 100644 --- a/src/Net/Listener.h +++ b/src/Net/Listener.h @@ -51,7 +51,7 @@ class Listener : private boost::noncopyable { public: Listener(Core::Application *application0, const std::string &x905CertFile0, const std::string &x905KeyFile0, - const boost::asio::ip::tcp::endpoint &address0 = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 6666)) throw(Core::Exception); + const boost::asio::ip::tcp::endpoint &address0) throw(Core::Exception); virtual ~Listener(); Core::Signals::Connection connectSignalNewConnection(const Core::Signals::Signal1 >::slot_type &slot) { diff --git a/src/Server/ConnectionManager.cpp b/src/Server/ConnectionManager.cpp index 4ac4f7c..96f383a 100644 --- a/src/Server/ConnectionManager.cpp +++ b/src/Server/ConnectionManager.cpp @@ -17,6 +17,7 @@ * with this program. If not, see . */ +#include #include "ConnectionManager.h" #include "Application.h" #include @@ -25,7 +26,6 @@ #include #include #include "Requests/DaemonStateUpdateRequest.h" -//#include "RequestHandlers/GSSAPIAuthRequestHandler.h" #include "RequestHandlers/ConnectionRequestHandlerGroup.h" #include "RequestHandlers/DaemonRequestHandlerGroup.h" #include "RequestHandlers/UserRequestHandlerGroup.h" @@ -71,6 +71,27 @@ void* ConnectionManager::ServerConnection::getPeerCertificate(size_t *size) cons return cert->data; }*/ +boost::asio::ip::tcp::endpoint ConnectionManager::parseAddress(const std::string &str) { + // TODO IPv6 + + if(str == "*") + return boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), DEFAULT_PORT); + + boost::smatch match; + + static const boost::regex r1("\\*:(\\d+)", boost::regex_constants::perl); + if(boost::regex_match(str, match, r1)) { + return boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), std::atoi(match[1].str().c_str())); + } + + static const boost::regex r2("(.+):(\\d+)", boost::regex_constants::perl); + if(boost::regex_match(str, match, r2)) { + return boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(match[1].str()), std::atoi(match[2].str().c_str())); + } + + return boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(str), DEFAULT_PORT); +} + void ConnectionManager::updateState(Common::HostInfo *hostInfo, Common::HostInfo::State state) { hostInfo->setState(state); @@ -89,7 +110,7 @@ bool ConnectionManager::handleConfigEntry(const Core::ConfigEntry &entry, bool h if(entry[0].getKey().matches("Listen") && entry[1].empty()) { try { - listenerAddresses.push_back(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(entry[0][0]), 6666)); + listenerAddresses.push_back(parseAddress(entry[0][0])); } catch(Core::Exception &e) { // TODO Log error @@ -136,9 +157,11 @@ bool ConnectionManager::handleConfigEntry(const Core::ConfigEntry &entry, bool h } void ConnectionManager::configFinished() { - if(listenerAddresses.empty()) { + if(listenerAddresses.empty()) + listenerAddresses.push_back(parseAddress("*")); + for(std::vector::const_iterator address = listenerAddresses.begin(); address != listenerAddresses.end(); ++address) { try { - boost::shared_ptr listener(new Net::Listener(application, x509CertFile, x509KeyFile)); + boost::shared_ptr listener(new Net::Listener(application, x509CertFile, x509KeyFile, *address)); listener->connectSignalNewConnection(boost::bind(&ConnectionManager::handleNewConnection, this, _1)); listeners.push_back(listener); } @@ -146,18 +169,6 @@ void ConnectionManager::configFinished() { // TODO Log error } } - else { - for(std::vector::const_iterator address = listenerAddresses.begin(); address != listenerAddresses.end(); ++address) { - try { - boost::shared_ptr listener(new Net::Listener(application, x509CertFile, x509KeyFile, *address)); - listener->connectSignalNewConnection(boost::bind(&ConnectionManager::handleNewConnection, this, _1)); - listeners.push_back(listener); - } - catch(Core::Exception &e) { - // TODO Log error - } - } - } } void ConnectionManager::handleNewConnection(boost::shared_ptr con) { diff --git a/src/Server/ConnectionManager.h b/src/Server/ConnectionManager.h index 6e3603b..5f41afa 100644 --- a/src/Server/ConnectionManager.h +++ b/src/Server/ConnectionManager.h @@ -109,6 +109,8 @@ class ConnectionManager : public Core::Configurable, private boost::noncopyable boost::shared_ptr daemonRequestHandlerGroup; boost::shared_ptr userRequestHandlerGroup; + static boost::asio::ip::tcp::endpoint parseAddress(const std::string &str); + void updateState(Common::HostInfo *hostInfo, Common::HostInfo::State state); void handleNewConnection(boost::shared_ptr con); diff --git a/src/mad-server.conf b/src/mad-server.conf index b6fc8c7..c19fb0f 100644 --- a/src/mad-server.conf +++ b/src/mad-server.conf @@ -2,7 +2,7 @@ Logger Console Logger File "mad-server.log" -#Listen * +Listen 127.0.0.1 X509TrustFile ../Cert/ca-cert.pem @@ -10,33 +10,39 @@ X509TrustFile ../Cert/ca-cert.pem X509CertFile ../Cert/cert.pem X509KeyFile ../Cert/key.pem -UserBackendMysql { - Username test - Password test - Database test +UserManager { + MinUid 1000 + MaxUid 29999 + + MinGid 1000 + MaxGid 29999 - Queries { - ListUsers "SELECT id, gid, username, fullname FROM users" - ListGroups "SELECT id, name FROM groups" - ListUserGroups "SELECT gid FROM usergroups WHERE uid = {UID}" - ListGroupUsers "SELECT uid FROM usergroups WHERE gid = {GID}" - UserById "SELECT id, gid, username, fullname FROM users WHERE id = {UID}" - UserByName "SELECT id, gid, username, fullname FROM users WHERE username = {USER}" - GroupById "SELECT id, name FROM groups WHERE id = {GID}" - GroupByName "SELECT id, name FROM groups WHERE name = {GROUP}" - UserGroupTable "SELECT uid, gid FROM usergroups" - AddUser "INSERT INTO users (id, gid, username, fullname) VALUES ({UID}, {GID}, {USER}, {FULL_NAME})" - UpdateUser "UPDATE users SET id = {UID}, gid = {GID}, username = {USER}, fullname = {FULL_NAME} WHERE id = {ORIG_UID}" - DeleteUser "DELETE FROM users WHERE id = {UID}" - AddUserToGroup "INSERT INTO usergroups (uid, gid) VALUES ({UID}, {GID})" - DeleteUserFromGroup "DELETE FROM usergroups WHERE uid = {UID} AND gid = {GID}" - } -} - -UserBackendHome { HomeDir "/tmp/home" Skeleton "/tmp/skel" - DirMode 0700 + UserDirMode 0700 + + Mysql { + Username test + Password test + Database test + + Queries { + ListUsers "SELECT id, gid, username, fullname FROM users" + ListGroups "SELECT id, name FROM groups" + ListUserGroups "SELECT gid FROM usergroups WHERE uid = {UID}" + ListGroupUsers "SELECT uid FROM usergroups WHERE gid = {GID}" + UserById "SELECT id, gid, username, fullname FROM users WHERE id = {UID}" + UserByName "SELECT id, gid, username, fullname FROM users WHERE username = {USER}" + GroupById "SELECT id, name FROM groups WHERE id = {GID}" + GroupByName "SELECT id, name FROM groups WHERE name = {GROUP}" + UserGroupTable "SELECT uid, gid FROM usergroups" + AddUser "INSERT INTO users (id, gid, username, fullname) VALUES ({UID}, {GID}, {USER}, {FULL_NAME})" + UpdateUser "UPDATE users SET id = {UID}, gid = {GID}, username = {USER}, fullname = {FULL_NAME} WHERE id = {ORIG_UID}" + DeleteUser "DELETE FROM users WHERE id = {UID}" + AddUserToGroup "INSERT INTO usergroups (uid, gid) VALUES ({UID}, {GID})" + DeleteUserFromGroup "DELETE FROM usergroups WHERE uid = {UID} AND gid = {GID}" + } + } } Daemon test { diff --git a/src/modules/UserBackendHome/UserBackendHome.cpp b/src/modules/UserBackendHome/UserBackendHome.cpp index f0714fe..445af72 100644 --- a/src/modules/UserBackendHome/UserBackendHome.cpp +++ b/src/modules/UserBackendHome/UserBackendHome.cpp @@ -31,11 +31,8 @@ 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")) { +bool UserBackendHome::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]; @@ -44,7 +41,7 @@ bool UserBackendHome::handleConfigEntry(const Core::ConfigEntry &entry, bool han if(entry[2].empty()) homeDir = entry[1][0]; } - else if(entry[1].getKey().matches("DirMode")) { + else if(entry[1].getKey().matches("UserDirMode")) { if(entry[2].empty()) { if(entry[1][0].empty()) { dirMode = 0755; diff --git a/src/modules/UserBackendMysql/UserBackendMysql.cpp b/src/modules/UserBackendMysql/UserBackendMysql.cpp index ebf86d5..3ef44d1 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.cpp +++ b/src/modules/UserBackendMysql/UserBackendMysql.cpp @@ -36,111 +36,113 @@ namespace UserBackendMysql { const std::string UserBackendMysql::name("UserBackendMysql"); -bool UserBackendMysql::handleConfigEntry(const Core::ConfigEntry &entry, bool handled) { - if(handled) +bool UserBackendMysql::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(!entry[0].getKey().matches("UserManager")) return false; - if(entry[0].getKey().matches("UserBackendMysql")) { - if(entry[1].getKey().matches("Host")) { - if(entry[2].empty()) - host = entry[1][0]; + if(entry[1].empty()) + return true; + + if(!entry[1].getKey().matches("Mysql")) + return false; + + if(entry[2].getKey().matches("Host")) { + if(entry[3].empty()) + host = entry[2][0]; + } + else if(entry[2].getKey().matches("Username")) { + if(entry[3].empty()) + username = entry[2][0]; + } + else if(entry[2].getKey().matches("Password")) { + if(entry[3].empty()) + passwd = entry[2][0]; + } + else if(entry[2].getKey().matches("Database")) { + if(entry[3].empty()) + db = entry[2][0]; + } + else if(entry[2].getKey().matches("Port")) { + if(entry[3].empty()) { + char *endptr; + long val; + + val = strtol(entry[2][0].c_str(), &endptr, 10); + + if(endptr != 0 || val < 0 || val > 65535) + application->log(Core::LoggerBase::WARNING, "UserBackendMysql: Invalid port"); + else + port = val; } - else if(entry[1].getKey().matches("Username")) { - if(entry[2].empty()) - username = entry[1][0]; + } + else if(entry[2].getKey().matches("UnixSocket")) { + if(entry[3].empty()) + unixSocket = entry[2][0]; + } + else if(entry[2].getKey().matches("Queries")) { + if(entry[3].getKey().matches("ListUsers")) { + if(entry[4].empty()) + queryListUsers = entry[3][0]; } - else if(entry[1].getKey().matches("Password")) { - if(entry[2].empty()) - passwd = entry[1][0]; + else if(entry[3].getKey().matches("ListGroups")) { + if(entry[4].empty()) + queryListGroups = entry[3][0]; } - else if(entry[1].getKey().matches("Database")) { - if(entry[2].empty()) - db = entry[1][0]; + else if(entry[3].getKey().matches("ListUserGroups")) { + if(entry[4].empty()) + queryListUserGroups = entry[3][0]; } - else if(entry[1].getKey().matches("Port")) { - if(entry[2].empty()) { - char *endptr; - long val; - - val = strtol(entry[1][0].c_str(), &endptr, 10); - - if(endptr != 0 || val < 0 || val > 65535) - application->log(Core::LoggerBase::WARNING, "UserBackendMysql: Invalid port"); - else - port = val; - } + else if(entry[3].getKey().matches("ListGroupUsers")) { + if(entry[4].empty()) + queryListGroupUsers = entry[3][0]; } - else if(entry[1].getKey().matches("UnixSocket")) { - if(entry[2].empty()) - unixSocket = entry[1][0]; + else if(entry[3].getKey().matches("UserById")) { + if(entry[4].empty()) + queryUserById = entry[3][0]; } - else if(entry[1].getKey().matches("Queries")) { - if(entry[2].getKey().matches("ListUsers")) { - if(entry[3].empty()) - queryListUsers = entry[2][0]; - } - else if(entry[2].getKey().matches("ListGroups")) { - if(entry[3].empty()) - queryListGroups = entry[2][0]; - } - else if(entry[2].getKey().matches("ListUserGroups")) { - if(entry[3].empty()) - queryListUserGroups = entry[2][0]; - } - else if(entry[2].getKey().matches("ListGroupUsers")) { - if(entry[3].empty()) - queryListGroupUsers = entry[2][0]; - } - else if(entry[2].getKey().matches("UserById")) { - if(entry[3].empty()) - queryUserById = entry[2][0]; - } - else if(entry[2].getKey().matches("UserByName")) { - if(entry[3].empty()) - queryUserByName = entry[2][0]; - } - else if(entry[2].getKey().matches("GroupById")) { - if(entry[3].empty()) - queryGroupById = entry[2][0]; - } - else if(entry[2].getKey().matches("GroupByName")) { - if(entry[3].empty()) - queryGroupByName = entry[2][0]; - } - else if(entry[2].getKey().matches("UserGroupTable")) { - if(entry[3].empty()) - queryUserGroupTable = entry[2][0]; - } - else if(entry[2].getKey().matches("AddUser")) { - if(entry[3].empty()) - queryAddUser = entry[2][0]; - } - else if(entry[2].getKey().matches("UpdateUser")) { - if(entry[3].empty()) - queryUpdateUser = entry[2][0]; - } - else if(entry[2].getKey().matches("DeleteUser")) { - if(entry[3].empty()) - queryDeleteUser = entry[2][0]; - } - else if(entry[2].getKey().matches("AddUserToGroup")) { - if(entry[3].empty()) - queryAddUserToGroup = entry[2][0]; - } - else if(entry[2].getKey().matches("DeleteUserFromGroup")) { - if(entry[3].empty()) - queryDeleteUserFromGroup = entry[2][0]; - } - else if(!entry[2].empty()) - return false; + else if(entry[3].getKey().matches("UserByName")) { + if(entry[4].empty()) + queryUserByName = entry[3][0]; + } + else if(entry[3].getKey().matches("GroupById")) { + if(entry[4].empty()) + queryGroupById = entry[3][0]; } - else if(!entry[1].empty()) + else if(entry[3].getKey().matches("GroupByName")) { + if(entry[4].empty()) + queryGroupByName = entry[3][0]; + } + else if(entry[3].getKey().matches("UserGroupTable")) { + if(entry[4].empty()) + queryUserGroupTable = entry[3][0]; + } + else if(entry[3].getKey().matches("AddUser")) { + if(entry[4].empty()) + queryAddUser = entry[3][0]; + } + else if(entry[3].getKey().matches("UpdateUser")) { + if(entry[4].empty()) + queryUpdateUser = entry[3][0]; + } + else if(entry[3].getKey().matches("DeleteUser")) { + if(entry[4].empty()) + queryDeleteUser = entry[3][0]; + } + else if(entry[3].getKey().matches("AddUserToGroup")) { + if(entry[4].empty()) + queryAddUserToGroup = entry[3][0]; + } + else if(entry[3].getKey().matches("DeleteUserFromGroup")) { + if(entry[4].empty()) + queryDeleteUserFromGroup = entry[3][0]; + } + else if(!entry[3].empty()) return false; - - return true; } + else if(!entry[2].empty()) + return false; - return false; + return true; } void UserBackendMysql::configFinished() { -- cgit v1.2.3