From 415cd36477e152c12f91a10ad61bb719373cd9d1 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 23 Aug 2009 20:57:00 +0200 Subject: =?UTF-8?q?Authentifikation=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Authenticators/PasswordAuthenticator.cpp | 71 +++++++++++++++ src/Client/Authenticators/PasswordAuthenticator.h | 57 ++++++++++++ src/Client/CMakeLists.txt | 2 + src/Common/Application.cpp | 4 +- src/Common/Application.h | 6 ++ src/Common/AuthBackend.h | 53 +++++++++++ src/Common/AuthContext.h | 36 ++++++++ src/Common/AuthManager.cpp | 58 ++++++++++++ src/Common/AuthManager.h | 84 +++++++++++++++++ src/Common/CMakeLists.txt | 3 + src/Common/Connection.h | 12 +-- src/Common/Requests/AuthMethodRequest.h | 38 ++++++++ src/Common/Requests/FSInfoRequest.h | 2 - src/Common/Requests/IdentifyRequest.h | 2 +- src/Common/Requests/StatusRequest.h | 2 - src/Core/Exception.cpp | 4 + src/Core/Exception.h | 3 +- .../RequestHandlers/CommandRequestHandler.cpp | 1 - src/Server/ConnectionManager.cpp | 50 +++++++---- src/Server/ConnectionManager.h | 27 ++++-- .../ConnectionRequestHandlerGroup.cpp | 45 ++++++++-- .../ConnectionRequestHandlerGroup.h | 2 + .../RequestHandlers/DaemonRequestHandlerGroup.cpp | 7 +- .../RequestHandlers/DaemonRequestHandlerGroup.h | 2 - src/mad-server.conf | 7 ++ src/madc.cpp | 18 ++-- src/modules/AuthBackendFile/AuthBackendFile.cpp | 100 +++++++++++++++++++++ src/modules/AuthBackendFile/AuthBackendFile.h | 80 +++++++++++++++++ src/modules/AuthBackendFile/CMakeLists.txt | 8 ++ src/modules/AuthBackendFile/Module.cpp | 30 +++++++ src/modules/AuthBackendFile/Module.h | 52 +++++++++++ src/modules/CMakeLists.txt | 1 + src/users | 1 + 33 files changed, 812 insertions(+), 56 deletions(-) create mode 100644 src/Client/Authenticators/PasswordAuthenticator.cpp create mode 100644 src/Client/Authenticators/PasswordAuthenticator.h create mode 100644 src/Common/AuthBackend.h create mode 100644 src/Common/AuthContext.h create mode 100644 src/Common/AuthManager.cpp create mode 100644 src/Common/AuthManager.h create mode 100644 src/Common/Requests/AuthMethodRequest.h create mode 100644 src/modules/AuthBackendFile/AuthBackendFile.cpp create mode 100644 src/modules/AuthBackendFile/AuthBackendFile.h create mode 100644 src/modules/AuthBackendFile/CMakeLists.txt create mode 100644 src/modules/AuthBackendFile/Module.cpp create mode 100644 src/modules/AuthBackendFile/Module.h create mode 100644 src/users diff --git a/src/Client/Authenticators/PasswordAuthenticator.cpp b/src/Client/Authenticators/PasswordAuthenticator.cpp new file mode 100644 index 0000000..44608db --- /dev/null +++ b/src/Client/Authenticators/PasswordAuthenticator.cpp @@ -0,0 +1,71 @@ +/* + * PasswordAuthenticator.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 "PasswordAuthenticator.h" + +#include + +namespace Mad { +namespace Client { +namespace Authenticators { + +void PasswordAuthenticator::PasswordAuthRequest::sendRequest() { + Common::XmlPacket packet; + packet.setType("Authenticate"); + packet.set("method", "Password"); + + packet.set("user", username); + std::vector challenge(password.begin(), password.end()); + packet.set("challenge", challenge); + + sendPacket(packet); +} + +void PasswordAuthenticator::PasswordAuthRequest::handlePacket(boost::shared_ptr packet) { + if(packet->getType() == "Error") { + signalFinished(Core::Exception(packet->get("Where"), static_cast(packet->get("ErrorCode")), + packet->get("SubCode"), packet->get("SubSubCode"))); + return; + } + else if(packet->getType() != "OK" && packet->getType() != "Continue") { + signalFinished(Core::Exception(Core::Exception::UNEXPECTED_PACKET)); + return; // TODO Logging + } + + signalFinished(packet); +} + +void PasswordAuthenticator::authenticate(Common::Application *application, Common::Connection *con, const std::string &username, const std::string &password) throw (Core::Exception) { + boost::shared_ptr request(new PasswordAuthRequest(application, username, password)); + + application->getRequestManager()->sendRequest(con, request); + request->wait(); + + std::pair, Core::Exception> result = request->getResult(); + + if(!result.first || result.second) + throw result.second; + + if(result.first->getType() != "OK") + throw Core::Exception(Core::Exception::NOT_AVAILABLE); +} + +} +} +} diff --git a/src/Client/Authenticators/PasswordAuthenticator.h b/src/Client/Authenticators/PasswordAuthenticator.h new file mode 100644 index 0000000..70c3cf1 --- /dev/null +++ b/src/Client/Authenticators/PasswordAuthenticator.h @@ -0,0 +1,57 @@ +/* + * PasswordAuthenticator.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_CLIENT_PASSWORDAUTHENTICATOR_H_ +#define MAD_CLIENT_PASSWORDAUTHENTICATOR_H_ + +#include "../export.h" + +#include + +namespace Mad { +namespace Client { +namespace Authenticators { + +class MAD_CLIENT_EXPORT PasswordAuthenticator { + private: + class MAD_CLIENT_EXPORT PasswordAuthRequest : public Common::Request { + private: + std::string username; + std::string password; + + protected: + virtual void sendRequest(); + virtual void handlePacket(boost::shared_ptr packet); + + public: + PasswordAuthRequest(Common::Application *application, const std::string &username0, const std::string &password0) + : Common::Request(application), username(username0), password(password0) {} + }; + + PasswordAuthenticator(); + + public: + static void authenticate(Common::Application *application, Common::Connection *con, const std::string &username, const std::string &password) throw (Core::Exception); +}; + +} +} +} + +#endif /* MAD_CLIENT_PASSWORDAUTHENTICATOR_H_ */ diff --git a/src/Client/CMakeLists.txt b/src/Client/CMakeLists.txt index 601ada8..5af7fdb 100644 --- a/src/Client/CMakeLists.txt +++ b/src/Client/CMakeLists.txt @@ -3,6 +3,8 @@ include_directories(${INCLUDES}) mad_library(Client export.h + Authenticators/PasswordAuthenticator.h Authenticators/PasswordAuthenticator.cpp + Requests/DaemonCommandRequest.h Requests/DaemonCommandRequest.cpp Requests/DaemonFSInfoRequest.h Requests/DaemonFSInfoRequest.cpp Requests/DaemonListRequest.h diff --git a/src/Common/Application.cpp b/src/Common/Application.cpp index 38ef4b5..196e57a 100644 --- a/src/Common/Application.cpp +++ b/src/Common/Application.cpp @@ -18,6 +18,7 @@ */ #include "Application.h" +#include "AuthManager.h" #include "ModuleManager.h" #include "RequestManager.h" #include "SystemManager.h" @@ -26,7 +27,7 @@ namespace Mad { namespace Common { -Application::Application(bool server) : moduleManager(new ModuleManager(this)), requestManager(new RequestManager(this, server)), +Application::Application(bool server) : authManager(new AuthManager), moduleManager(new ModuleManager(this)), requestManager(new RequestManager(this, server)), systemManager(new SystemManager), userManager(new UserManager(this)) {} Application::~Application() { @@ -34,6 +35,7 @@ Application::~Application() { delete systemManager; delete requestManager; delete moduleManager; + delete authManager; } } diff --git a/src/Common/Application.h b/src/Common/Application.h index 6de3b07..39cf2de 100644 --- a/src/Common/Application.h +++ b/src/Common/Application.h @@ -27,6 +27,7 @@ namespace Mad { namespace Common { +class AuthManager; class ModuleManager; class RequestManager; class SystemManager; @@ -34,6 +35,7 @@ class UserManager; class MAD_COMMON_EXPORT Application : public Core::Application { private: + AuthManager *authManager; ModuleManager *moduleManager; RequestManager *requestManager; SystemManager *systemManager; @@ -44,6 +46,10 @@ class MAD_COMMON_EXPORT Application : public Core::Application { virtual ~Application(); public: + AuthManager* getAuthManager() const { + return authManager; + } + ModuleManager* getModuleManager() const { return moduleManager; } diff --git a/src/Common/AuthBackend.h b/src/Common/AuthBackend.h new file mode 100644 index 0000000..e933856 --- /dev/null +++ b/src/Common/AuthBackend.h @@ -0,0 +1,53 @@ +/* + * AuthBackend.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_COMMON_AUTHBACKEND_H_ +#define MAD_COMMON_AUTHBACKEND_H_ + +#include + +#include + +#include +#include + +namespace Mad { +namespace Common { + +class AuthContext; +class AuthManager; + +class AuthBackend { + protected: + friend class AuthManager; + + virtual const std::vector& getMethods() const = 0; + + virtual boost::shared_ptr authenticate(const std::string& /*method*/, const std::string& /*user*/, + const std::vector& /*challenge*/, std::vector& /*response*/, + boost::shared_ptr /*context*/) throw(Core::Exception) = 0; + + public: + virtual ~AuthBackend() {} +}; + +} +} + +#endif /* MAD_COMMON_AUTHBACKEND_H_ */ diff --git a/src/Common/AuthContext.h b/src/Common/AuthContext.h new file mode 100644 index 0000000..b402dd3 --- /dev/null +++ b/src/Common/AuthContext.h @@ -0,0 +1,36 @@ +/* + * AuthContext.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_COMMON_AUTHCONTEXT_H_ +#define MAD_COMMON_AUTHCONTEXT_H_ + +namespace Mad { +namespace Common { + +class AuthContext { + public: + virtual bool isAuthenticated() const = 0; + + virtual ~AuthContext() {} +}; + +} +} + +#endif /* MAD_COMMON_AUTHCONTEXT_H_ */ diff --git a/src/Common/AuthManager.cpp b/src/Common/AuthManager.cpp new file mode 100644 index 0000000..b27c29f --- /dev/null +++ b/src/Common/AuthManager.cpp @@ -0,0 +1,58 @@ +/* + * AuthManager.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 "AuthManager.h" + +#include "AuthBackend.h" + +namespace Mad { +namespace Common { + +const std::vector AuthManager::DenyBackend::methods; + +void AuthManager::registerBackend(boost::shared_ptr newBackend) { + boost::lock_guard lock(mutex); + + backend = newBackend; +} + +void AuthManager::unregisterBackend(boost::shared_ptr oldBackend) { + boost::lock_guard lock(mutex); + + if(oldBackend == backend) + backend = denyBackend; +} + +std::vector AuthManager::getMethods() { + boost::shared_lock lock(mutex); + + return backend->getMethods(); +} + +boost::shared_ptr AuthManager::authenticate(const std::string &method, const std::string &user, const std::vector &challenge, + std::vector &response, boost::shared_ptr context) throw(Core::Exception) { + boost::lock_guard lock(mutex); + + response.clear(); + + return backend->authenticate(method, user, challenge, response, context); +} + +} +} diff --git a/src/Common/AuthManager.h b/src/Common/AuthManager.h new file mode 100644 index 0000000..c773214 --- /dev/null +++ b/src/Common/AuthManager.h @@ -0,0 +1,84 @@ +/* + * AuthManager.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_COMMON_AUTHMANAGER_H_ +#define MAD_COMMON_AUTHMANAGER_H_ + +#include "export.h" + +#include "AuthBackend.h" +#include "AuthContext.h" + +#include + +#include + +#include +#include +#include + +#include + +namespace Mad { +namespace Common { + +class Application; + +class MAD_COMMON_EXPORT AuthManager : private boost::noncopyable { + private: + friend class Application; + + class DenyBackend : public AuthBackend { + private: + const static std::vector methods; + + protected: + virtual const std::vector& getMethods() const { + return methods; + } + + virtual boost::shared_ptr authenticate(const std::string& /*method*/, const std::string& /*user*/, + const std::vector& /*challenge*/, std::vector& /*response*/, + boost::shared_ptr /*context*/) throw(Core::Exception) { + throw Core::Exception(Core::Exception::NOT_IMPLEMENTED); + } + }; + + boost::shared_ptr denyBackend; + + boost::shared_ptr backend; + + boost::shared_mutex mutex; + + AuthManager() : denyBackend(new DenyBackend), backend(denyBackend) {} + + public: + void registerBackend(boost::shared_ptr newBackend); + void unregisterBackend(boost::shared_ptr oldBackend); + + std::vector getMethods(); + + boost::shared_ptr authenticate(const std::string &method, const std::string &user, const std::vector &challenge, + std::vector &response, boost::shared_ptr context = boost::shared_ptr()) throw(Core::Exception); +}; + +} +} + +#endif /* MAD_COMMON_AUTHMANAGER_H_ */ diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index 4ddcd07..13e1599 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -18,6 +18,9 @@ mad_library(Common Requests/StatusRequest.h Application.cpp Application.h + AuthBackend.h + AuthContext.h + AuthManager.cpp AuthManager.h Base64Encoder.cpp Base64Encoder.h ClientConnection.cpp ClientConnection.h Connection.cpp Connection.h diff --git a/src/Common/Connection.h b/src/Common/Connection.h index e0c9ce6..bcf6c44 100644 --- a/src/Common/Connection.h +++ b/src/Common/Connection.h @@ -39,12 +39,10 @@ class XmlPacket; class MAD_COMMON_EXPORT Connection : private boost::noncopyable { private: - bool authenticated; - Core::Signals::Signal2, boost::uint16_t> signalReceive; protected: - Connection(Core::Application *application) : authenticated(0), signalReceive(application) {} + Connection(Core::Application *application) : signalReceive(application) {} void receive(boost::shared_ptr packet); @@ -66,14 +64,6 @@ class MAD_COMMON_EXPORT Connection : private boost::noncopyable { virtual bool disconnect() = 0; //virtual void* getCertificate(size_t *size) const = 0; //virtual void* getPeerCertificate(size_t *size) const = 0; - - void setAuthenticated() { - authenticated = true; - } - - bool isAuthenticated() const { - return authenticated; - } }; } diff --git a/src/Common/Requests/AuthMethodRequest.h b/src/Common/Requests/AuthMethodRequest.h new file mode 100644 index 0000000..e8199fd --- /dev/null +++ b/src/Common/Requests/AuthMethodRequest.h @@ -0,0 +1,38 @@ +/* + * AuthMethodRequest.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_COMMON_REQUESTS_AUTHMETHODREQUEST_H_ +#define MAD_COMMON_REQUESTS_AUTHMETHODREQUEST_H_ + +#include "SimpleRequest.h" + +namespace Mad { +namespace Common { +namespace Requests { + +class AuthMethodRequest : public SimpleRequest { + public: + AuthMethodRequest(Application *application) : SimpleRequest(application, "GetAuthMethods") {} +}; + +} +} +} + +#endif /* MAD_COMMON_REQUESTS_AUTHMETHODREQUEST_H_ */ diff --git a/src/Common/Requests/FSInfoRequest.h b/src/Common/Requests/FSInfoRequest.h index 14aff57..223b7a4 100644 --- a/src/Common/Requests/FSInfoRequest.h +++ b/src/Common/Requests/FSInfoRequest.h @@ -20,8 +20,6 @@ #ifndef MAD_COMMON_REQUESTS_FSINFOREQUEST_H_ #define MAD_COMMON_REQUESTS_FSINFOREQUEST_H_ -#include "../export.h" - #include "SimpleRequest.h" namespace Mad { diff --git a/src/Common/Requests/IdentifyRequest.h b/src/Common/Requests/IdentifyRequest.h index e2e1399..51b24dd 100644 --- a/src/Common/Requests/IdentifyRequest.h +++ b/src/Common/Requests/IdentifyRequest.h @@ -38,7 +38,7 @@ class MAD_COMMON_EXPORT IdentifyRequest : public Common::Request { virtual void sendRequest(); public: - IdentifyRequest(Application *application, const std::string &hostname0 = std::string()) : Request(application), hostname(hostname0) {} + IdentifyRequest(Application *application, const std::string &hostname0) : Request(application), hostname(hostname0) {} }; } diff --git a/src/Common/Requests/StatusRequest.h b/src/Common/Requests/StatusRequest.h index 0569a72..09f4d90 100644 --- a/src/Common/Requests/StatusRequest.h +++ b/src/Common/Requests/StatusRequest.h @@ -20,8 +20,6 @@ #ifndef MAD_COMMON_REQUESTS_STATUSREQUEST_H_ #define MAD_COMMON_REQUESTS_STATUSREQUEST_H_ -#include "../export.h" - #include "SimpleRequest.h" namespace Mad { diff --git a/src/Core/Exception.cpp b/src/Core/Exception.cpp index af39654..0029613 100644 --- a/src/Core/Exception.cpp +++ b/src/Core/Exception.cpp @@ -47,6 +47,8 @@ std::string Exception::strerror() const { return ret + "Not found"; case INVALID_INPUT: return ret + "Invalid input"; + case PERMISSION: + return ret + "Permission denied"; case INTERNAL_ERRNO: return ret + std::strerror(subCode); case INVALID_ADDRESS: @@ -57,6 +59,8 @@ std::string Exception::strerror() const { return ret + "The daemon is unknown"; case DUPLICATE_ENTRY: return ret + "Duplicate entry"; + case AUTHENTICATION: + return ret + "Authentication failure"; default: return ret + "Unknown error"; } diff --git a/src/Core/Exception.h b/src/Core/Exception.h index 15ff749..fb6fae7 100644 --- a/src/Core/Exception.h +++ b/src/Core/Exception.h @@ -31,11 +31,12 @@ class MAD_CORE_EXPORT Exception { public: enum ErrorCode { SUCCESS = 0x0000, UNEXPECTED_PACKET = 0x0001, INVALID_ACTION = 0x0002, NOT_AVAILABLE = 0x0003, NOT_FINISHED = 0x0004, NOT_IMPLEMENTED = 0x0005, - NOT_FOUND = 0x0006, INVALID_INPUT = 0x0007, + NOT_FOUND = 0x0006, INVALID_INPUT = 0x0007, PERMISSION = 0x0008, INTERNAL_ERRNO = 0x0010, INVALID_ADDRESS = 0x0020, ALREADY_IDENTIFIED = 0x0030, UNKNOWN_DAEMON = 0x0031, DUPLICATE_ENTRY = 0x0040, + AUTHENTICATION = 0x0050, }; private: diff --git a/src/Daemon/RequestHandlers/CommandRequestHandler.cpp b/src/Daemon/RequestHandlers/CommandRequestHandler.cpp index 8ac5ec5..9be8a5b 100644 --- a/src/Daemon/RequestHandlers/CommandRequestHandler.cpp +++ b/src/Daemon/RequestHandlers/CommandRequestHandler.cpp @@ -26,7 +26,6 @@ namespace RequestHandlers { void CommandRequestHandler::handleRequest(boost::shared_ptr packet, Common::XmlPacket *ret) { // TODO Require authentication - // TODO Error handling std::string command = packet->get("command"); diff --git a/src/Server/ConnectionManager.cpp b/src/Server/ConnectionManager.cpp index 160f3c3..e52e8c4 100644 --- a/src/Server/ConnectionManager.cpp +++ b/src/Server/ConnectionManager.cpp @@ -22,6 +22,7 @@ #include "Application.h" #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #include #include -//#include #include namespace Mad { @@ -42,8 +42,8 @@ bool ConnectionManager::ServerConnection::send(const Net::Packet &packet) { return connection->send(packet); } -ConnectionManager::ServerConnection::ServerConnection(Core::Application *application, boost::shared_ptr connection0) -: Common::Connection(application), connection(connection0), type(UNKNOWN), hostInfo(0) { +ConnectionManager::ServerConnection::ServerConnection(Common::Application *application0, boost::shared_ptr connection0) +: Common::Connection(application0), application(application0), connection(connection0), type(UNKNOWN), hostInfo(0) { connection->connectSignalReceive(boost::bind(&ServerConnection::receive, this, _1)); } @@ -57,6 +57,16 @@ bool ConnectionManager::ServerConnection::disconnect() { return true; } +boost::shared_ptr ConnectionManager::ServerConnection::authenticate(const std::string &method, + const std::string &user, const std::vector &challenge, std::vector &response) { + if(!isIdentified()) + type = CLIENT; + + authContext = application->getAuthManager()->authenticate(method, user, challenge, response, authContext); + + return authContext; +} + /*void* ConnectionManager::ServerConnection::getCertificate(size_t *size) const { const gnutls_datum_t *cert = connection->getCertificate(); @@ -203,7 +213,6 @@ ConnectionManager::ConnectionManager(Application *application0) : application(ap connectionRequestHandlerGroup(new RequestHandlers::ConnectionRequestHandlerGroup(application)), daemonRequestHandlerGroup(new RequestHandlers::DaemonRequestHandlerGroup), userRequestHandlerGroup(new RequestHandlers::UserRequestHandlerGroup(application)) { - //requestManager->registerPacketType("AuthGSSAPI"); application->getRequestManager()->registerPacketType("FSInfo"); application->getRequestManager()->registerPacketType("GetStatus"); @@ -223,12 +232,11 @@ ConnectionManager::~ConnectionManager() { application->getRequestManager()->unregisterRequestHandlerGroup(daemonRequestHandlerGroup); application->getRequestManager()->unregisterRequestHandlerGroup(connectionRequestHandlerGroup); - //requestManager->unregisterPacketType("AuthGSSAPI"); application->getRequestManager()->unregisterPacketType("FSInfo"); application->getRequestManager()->unregisterPacketType("GetStatus"); } -boost::shared_ptr ConnectionManager::getDaemonConnection(const std::string &name) const throw (Core::Exception&) { +boost::shared_ptr ConnectionManager::getDaemonConnection(const std::string &name) const throw (Core::Exception) { std::map::const_iterator hostIt = daemonInfo.find(name); @@ -248,7 +256,7 @@ boost::shared_ptr ConnectionManager::getDaemonConnection(con throw Core::Exception(Core::Exception::NOT_AVAILABLE); } -std::string ConnectionManager::getDaemonName(const Common::Connection *con) const throw (Core::Exception&) { +std::string ConnectionManager::getDaemonName(const Common::Connection *con) const throw (Core::Exception) { const ServerConnection *connection = dynamic_cast(con); if(connection && connection->getConnectionType() == ServerConnection::DAEMON) @@ -257,13 +265,13 @@ std::string ConnectionManager::getDaemonName(const Common::Connection *con) cons throw Core::Exception(Core::Exception::UNKNOWN_DAEMON); } -void ConnectionManager::identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Core::Exception&) { +void ConnectionManager::identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Core::Exception) { // TODO Logging ServerConnection *connection = dynamic_cast(con); if(!connection) - throw Core::Exception(Core::Exception::INVALID_ACTION); + throw Core::Exception(Core::Exception::INVALID_INPUT); if(connection->isIdentified()) throw Core::Exception(Core::Exception::ALREADY_IDENTIFIED); @@ -283,20 +291,21 @@ void ConnectionManager::identifyDaemonConnection(Common::Connection *con, const connection->identify(hostInfo); updateState(hostInfo, Common::HostInfo::RUNNING); - - application->logf("Identified as '%s'.", name.c_str()); } -void ConnectionManager::identifyClientConnection(Common::Connection *con) throw (Core::Exception&) { +boost::shared_ptr ConnectionManager::authenticateConnection(Common::Connection *con, const std::string &method, + const std::string &user, const std::vector &challenge, std::vector &response) { + // TODO Logging + ServerConnection *connection = dynamic_cast(con); if(!connection) - throw Core::Exception(Core::Exception::INVALID_ACTION); + throw Core::Exception(Core::Exception::INVALID_INPUT); - if(connection->isIdentified()) - throw Core::Exception(Core::Exception::ALREADY_IDENTIFIED); + if(!connection->isIdentified()) + connection->identify(); - connection->identify(); + return connection->authenticate(method, user, challenge, response); } std::vector ConnectionManager::getDaemonList() const { @@ -309,5 +318,14 @@ std::vector ConnectionManager::getDaemonList() const { return ret; } +bool ConnectionManager::isAuthenticated(Common::Connection *con) const { + ServerConnection *connection = dynamic_cast(con); + + if(!connection) + throw Core::Exception(Core::Exception::INVALID_INPUT); + + return connection->isAuthenticated(); +} + } } diff --git a/src/Server/ConnectionManager.h b/src/Server/ConnectionManager.h index bdf1b4d..e045a6a 100644 --- a/src/Server/ConnectionManager.h +++ b/src/Server/ConnectionManager.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -49,22 +50,25 @@ class Application; class MAD_SERVER_EXPORT ConnectionManager : public Core::Configurable, private boost::noncopyable { private: - class ServerConnection : public Common::Connection { + class MAD_SERVER_EXPORT ServerConnection : public Common::Connection { public: enum ConnectionType { UNKNOWN = 0, DAEMON, CLIENT }; private: + Common::Application *application; + boost::shared_ptr connection; ConnectionType type; Common::HostInfo *hostInfo; + boost::shared_ptr authContext; protected: virtual bool send(const Net::Packet &packet); public: - ServerConnection(Core::Application *application, boost::shared_ptr connection0); + ServerConnection(Common::Application *application0, boost::shared_ptr connection0); bool isConnected() const; @@ -92,6 +96,13 @@ class MAD_SERVER_EXPORT ConnectionManager : public Core::Configurable, private b type = DAEMON; hostInfo = info; } + + bool isAuthenticated() const { + return (authContext.get() != 0 && authContext->isAuthenticated()); + } + + boost::shared_ptr authenticate(const std::string &method, const std::string &user, + const std::vector &challenge, std::vector &response); }; friend class Application; @@ -126,11 +137,15 @@ class MAD_SERVER_EXPORT ConnectionManager : public Core::Configurable, private b virtual void configFinished(); public: - boost::shared_ptr getDaemonConnection(const std::string &name) const throw (Core::Exception&); - std::string getDaemonName(const Common::Connection *con) const throw (Core::Exception&); + boost::shared_ptr getDaemonConnection(const std::string &name) const throw (Core::Exception); + std::string getDaemonName(const Common::Connection *con) const throw (Core::Exception); + + void identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Core::Exception); + + boost::shared_ptr authenticateConnection(Common::Connection *con, const std::string &method, + const std::string &user, const std::vector &challenge, std::vector &response); - void identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Core::Exception&); - void identifyClientConnection(Common::Connection *con) throw (Core::Exception&); + bool isAuthenticated(Common::Connection *con) const; std::vector getDaemonList() const; }; diff --git a/src/Server/RequestHandlers/ConnectionRequestHandlerGroup.cpp b/src/Server/RequestHandlers/ConnectionRequestHandlerGroup.cpp index e94853f..b59cc3d 100644 --- a/src/Server/RequestHandlers/ConnectionRequestHandlerGroup.cpp +++ b/src/Server/RequestHandlers/ConnectionRequestHandlerGroup.cpp @@ -21,6 +21,8 @@ #include "../Application.h" #include "../ConnectionManager.h" +#include + #include #include @@ -29,9 +31,41 @@ namespace Mad { namespace Server { namespace RequestHandlers { -void ConnectionRequestHandlerGroup::handleDaemonListRequest(boost::shared_ptr /*packet*/, Common::XmlPacket *ret, +void ConnectionRequestHandlerGroup::handleAuthMethodRequest(boost::shared_ptr /*packet*/, Common::XmlPacket *ret, Common::Connection* /*connection*/) { - // TODO Require authentication + ret->setType("OK"); + + Common::XmlPacket::List *list = ret->createList("methods"); + + const std::vector &methods = application->getAuthManager()->getMethods(); + + for(std::vector::const_iterator method = methods.begin(); method != methods.end(); ++method) { + Common::XmlPacket::List::iterator entry = list->addEntry(); + + entry->set("name", *method); + } +} + +void ConnectionRequestHandlerGroup::handleAuthRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection) { + std::vector response; + + boost::shared_ptr authContext = application->getConnectionManager()->authenticateConnection(connection, + packet->get("method"), packet->get("user"), + packet->get&>("challenge"), response); + + if(!response.empty()) + ret->set("response", response); + + if(authContext->isAuthenticated()) + ret->setType("OK"); + else + ret->setType("Continue"); +} + +void ConnectionRequestHandlerGroup::handleDaemonListRequest(boost::shared_ptr /*packet*/, Common::XmlPacket *ret, + Common::Connection *connection) { + if(!application->getConnectionManager()->isAuthenticated(connection)) + throw(Core::Exception(Core::Exception::PERMISSION)); ret->setType("OK"); Common::XmlPacket::List *list = ret->createList("hosts"); @@ -48,10 +82,7 @@ void ConnectionRequestHandlerGroup::handleDaemonListRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection) { - if(packet->get("hostname").empty()) - application->getConnectionManager()->identifyClientConnection(connection); - else - application->getConnectionManager()->identifyDaemonConnection(connection, packet->get("hostname")); + application->getConnectionManager()->identifyDaemonConnection(connection, packet->get("hostname")); ret->setType("OK"); } @@ -85,6 +116,8 @@ void ConnectionRequestHandlerGroup::handleLogRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection); + void handleAuthRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection); void handleDaemonListRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection); void handleIdentifyRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection); void handleLogRequest(boost::shared_ptr packet, Common::XmlPacket *ret, Common::Connection *connection); diff --git a/src/Server/RequestHandlers/DaemonRequestHandlerGroup.cpp b/src/Server/RequestHandlers/DaemonRequestHandlerGroup.cpp index 0345d7b..ee79ff2 100644 --- a/src/Server/RequestHandlers/DaemonRequestHandlerGroup.cpp +++ b/src/Server/RequestHandlers/DaemonRequestHandlerGroup.cpp @@ -44,10 +44,13 @@ void DaemonRequestHandlerGroup::DaemonRequestHandler::handlePacket(boost::shared return; } - // TODO Require authentication + ConnectionManager *connectionManager = dynamic_cast(*getApplication()).getConnectionManager(); + + if(!connectionManager->isAuthenticated(getConnection())) + throw(Core::Exception(Core::Exception::PERMISSION)); try { - boost::shared_ptr daemonCon = dynamic_cast(*getApplication()).getConnectionManager()->getDaemonConnection(packet->get("daemon")); + boost::shared_ptr daemonCon = connectionManager->getDaemonConnection(packet->get("daemon")); boost::shared_ptr request; if(type == "DaemonCommand") diff --git a/src/Server/RequestHandlers/DaemonRequestHandlerGroup.h b/src/Server/RequestHandlers/DaemonRequestHandlerGroup.h index 086bf16..8312709 100644 --- a/src/Server/RequestHandlers/DaemonRequestHandlerGroup.h +++ b/src/Server/RequestHandlers/DaemonRequestHandlerGroup.h @@ -47,8 +47,6 @@ class MAD_SERVER_EXPORT DaemonRequestHandlerGroup : public Common::RequestHandle : Common::RequestHandler(application), type(type0) {} }; - ConnectionManager *connectionManager; - std::set types; public: diff --git a/src/mad-server.conf b/src/mad-server.conf index b419a42..88213e6 100644 --- a/src/mad-server.conf +++ b/src/mad-server.conf @@ -1,4 +1,7 @@ LoadModule "FileLogger" + +LoadModule "AuthBackendFile" + LoadModule "SystemBackendPosix" LoadModule "SystemBackendProc" @@ -18,6 +21,10 @@ X509TrustFile ../Cert/ca-cert.pem X509CertFile ../Cert/cert.pem X509KeyFile ../Cert/key.pem +AuthBackendFile { + File "users" +} + UserManager { MinUid 1000 MaxUid 29999 diff --git a/src/madc.cpp b/src/madc.cpp index c55fd3e..1fa2112 100644 --- a/src/madc.cpp +++ b/src/madc.cpp @@ -30,6 +30,8 @@ #include "Client/Application.h" #include "Client/CommandParser.h" #include "Client/InformationManager.h" +#include "Client/PasswordReader.h" +#include "Client/Authenticators/PasswordAuthenticator.h" #include @@ -69,13 +71,19 @@ int main(int argc, char *argv[]) { application.getRequestManager()->registerConnection(connection); + std::cerr << " connected." << std::endl << std::endl; + { - boost::shared_ptr request(new Common::Requests::IdentifyRequest(&application)); - application.getRequestManager()->sendRequest(connection, request); - request->wait(); + std::string username, password; + + std::cerr << "Login: " << std::flush; + std::getline(std::cin, username); + password = Client::PasswordReader::readPassword("Password: "); + + Client::Authenticators::PasswordAuthenticator::authenticate(&application, connection, username, password); } - std::cerr << " connected." << std::endl; + std::cerr << "Login successful." << std::endl << std::endl; std::cerr << "Receiving host list..." << std::flush; application.getInformationManager()->updateDaemonList(connection); @@ -108,7 +116,7 @@ int main(int argc, char *argv[]) { application.getRequestManager()->unregisterConnection(connection); } catch(Core::Exception &e) { - application.logf(Core::LoggerBase::LOG_CRITICAL, "Connection error: %s", e.strerror().c_str()); + application.logf(Core::LoggerBase::LOG_CRITICAL, "Error: %s", e.strerror().c_str()); } delete connection; diff --git a/src/modules/AuthBackendFile/AuthBackendFile.cpp b/src/modules/AuthBackendFile/AuthBackendFile.cpp new file mode 100644 index 0000000..8374101 --- /dev/null +++ b/src/modules/AuthBackendFile/AuthBackendFile.cpp @@ -0,0 +1,100 @@ +/* + * AuthBackendFile.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 "AuthBackendFile.h" +#include +#include + +#include + +#include + +namespace Mad { +namespace Modules { +namespace AuthBackendFile { + +void AuthBackendFile::readFile(const std::string &name) { + std::ifstream stream(name.c_str()); + if(!stream.good()) { + application->logf(Core::LoggerBase::LOG_WARNING, "AuthBackendFile: Can't read file '%s'.", name.c_str()); + return; + } + + while(stream.good() && !stream.eof()) { + std::string line; + std::getline(stream, line); + + if(line.empty()) + continue; + + static const boost::regex regex("([^:]+):(.+)", boost::regex_constants::perl); + boost::smatch match; + + if(!boost::regex_match(line, match, regex)) { + application->logf(Core::LoggerBase::LOG_WARNING, "AuthBackendFile: Malformed line in file '%s'.", name.c_str()); + continue; + } + + + userMap.insert(std::make_pair(match[1].str(), match[2].str())); + } +} + +bool AuthBackendFile::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(!entry[0].getKey().matches("AuthBackendFile")) + return false; + + if(entry[1].empty()) + return true; + + if(entry[1].getKey().matches("File")) { + if(entry[2].empty()) { + readFile(entry[1][0]); + } + } + else if(!entry[2].empty()) + return false; + + return true; +} + +boost::shared_ptr AuthBackendFile::authenticate(const std::string &method, const std::string &user, + const std::vector &challenge, std::vector& /*response*/, + boost::shared_ptr context) throw(Core::Exception) { + if(method != "Password") + throw(Core::Exception(Core::Exception::INVALID_INPUT)); + + if(context.get() != 0 && dynamic_cast(context.get()) == 0) + throw(Core::Exception(Core::Exception::INVALID_INPUT)); + + if(context.get() == 0) + context.reset(new AuthContextFile); + + std::string password(challenge.begin(), challenge.end()); + + std::map::iterator userIt = userMap.find(user); + if(userIt == userMap.end() || password != userIt->second) + throw(Core::Exception(Core::Exception::AUTHENTICATION)); + + return context; +} + +} +} +} diff --git a/src/modules/AuthBackendFile/AuthBackendFile.h b/src/modules/AuthBackendFile/AuthBackendFile.h new file mode 100644 index 0000000..81e7d12 --- /dev/null +++ b/src/modules/AuthBackendFile/AuthBackendFile.h @@ -0,0 +1,80 @@ +/* + * AuthBackendFile.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_AUTHBACKENDFILE_AUTHBACKENDFILE_H_ +#define MAD_MODULES_AUTHBACKENDFILE_AUTHBACKENDFILE_H_ + +#include "../export.h" + +#include +#include +#include + +#include +#include + +namespace Mad { +namespace Modules { +namespace AuthBackendFile { + +class MAD_MODULE_EXPORT AuthBackendFile : public Common::AuthBackend, private Core::Configurable, private boost::noncopyable { + private: + class AuthContextFile : public Common::AuthContext { + protected: + virtual bool isAuthenticated() const { + return true; + } + }; + + void readFile(const std::string &name); + + std::vector methods; + + Common::Application *application; + + std::map userMap; + + protected: + virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/); + + virtual const std::vector& getMethods() const { + return methods; + } + + virtual boost::shared_ptr authenticate(const std::string &method, const std::string &user, + const std::vector &challenge, std::vector &response, + boost::shared_ptr context) throw(Core::Exception); + + public: + AuthBackendFile(Common::Application *application0) : application(application0) { + methods.push_back("Password"); + + application->getConfigManager()->registerConfigurable(this); + } + + virtual ~AuthBackendFile() { + application->getConfigManager()->unregisterConfigurable(this); + } +}; + +} +} +} + +#endif /* MAD_MODULES_AUTHBACKENDFILE_AUTHBACKENDFILE_H_ */ diff --git a/src/modules/AuthBackendFile/CMakeLists.txt b/src/modules/AuthBackendFile/CMakeLists.txt new file mode 100644 index 0000000..3afd71f --- /dev/null +++ b/src/modules/AuthBackendFile/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${INCLUDES}) + +mad_module(AuthBackendFile + Module.cpp Module.h + AuthBackendFile.cpp AuthBackendFile.h +) + +mad_module_libraries(AuthBackendFile) diff --git a/src/modules/AuthBackendFile/Module.cpp b/src/modules/AuthBackendFile/Module.cpp new file mode 100644 index 0000000..e5a9a18 --- /dev/null +++ b/src/modules/AuthBackendFile/Module.cpp @@ -0,0 +1,30 @@ +/* + * 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 "../export.h" + +#include "Module.h" + +extern "C" { + +MAD_MODULE_EXPORT Mad::Common::Module* AuthBackendFile_create(Mad::Common::Application *application) { + return new Mad::Modules::AuthBackendFile::Module(application); +} + +} diff --git a/src/modules/AuthBackendFile/Module.h b/src/modules/AuthBackendFile/Module.h new file mode 100644 index 0000000..b0d14aa --- /dev/null +++ b/src/modules/AuthBackendFile/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_AUTHBACKENDFILE_MODULE_H_ +#define MAD_MODULES_AUTHBACKENDFILE_MODULE_H_ + +#include "AuthBackendFile.h" + +#include +#include + +namespace Mad { +namespace Modules { +namespace AuthBackendFile { + +class Module : public Common::Module { + private: + Common::Application *application; + + boost::shared_ptr backend; + + public: + Module(Common::Application *application0) : application(application0), backend(new AuthBackendFile(application)) { + application->getAuthManager()->registerBackend(backend); + } + + virtual ~Module() { + application->getAuthManager()->unregisterBackend(backend); + } +}; + +} +} +} + +#endif /* MAD_MODULES_AUTHBACKENDFILE_MODULE_H_ */ diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 7e11214..e5890f4 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -33,6 +33,7 @@ macro(mad_module_libraries name) endif(WITH_${upper_name}) endmacro(mad_module_libraries) +add_subdirectory(AuthBackendFile) add_subdirectory(FileLogger) if(UNIX) diff --git a/src/users b/src/users new file mode 100644 index 0000000..93dc7d2 --- /dev/null +++ b/src/users @@ -0,0 +1 @@ +root:admin -- cgit v1.2.3