From c1cb92bc30256171bfafb22cf8512142afee97cf Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 15 Aug 2009 15:07:41 +0200 Subject: =?UTF-8?q?UserConfigBackendKrb5=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 +- src/mad-server.conf | 5 + src/mad-server.cpp | 1 + src/modules/CMakeLists.txt | 4 + src/modules/UserConfigBackendKrb5/CMakeLists.txt | 8 + src/modules/UserConfigBackendKrb5/Module.cpp | 28 +++ src/modules/UserConfigBackendKrb5/Module.h | 52 ++++++ .../UserConfigBackendKrb5.cpp | 189 +++++++++++++++++++++ .../UserConfigBackendKrb5/UserConfigBackendKrb5.h | 97 +++++++++++ 9 files changed, 385 insertions(+), 2 deletions(-) create mode 100644 src/modules/UserConfigBackendKrb5/CMakeLists.txt create mode 100644 src/modules/UserConfigBackendKrb5/Module.cpp create mode 100644 src/modules/UserConfigBackendKrb5/Module.h create mode 100644 src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.cpp create mode 100644 src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8da14e2..bbfb89a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,10 @@ set(CMAKE_MODULE_PATH ${MAD_SOURCE_DIR}) find_package(LibXml2 REQUIRED) find_package(DL REQUIRED) find_package(Readline REQUIRED) -#find_package(KRB5 REQUIRED gssapi) find_package(OpenSSL REQUIRED) find_package(Boost REQUIRED date_time filesystem regex signals system thread) find_package(MySQL) +find_package(KRB5 COMPONENTS krb5 kadm-client) configure_file(${MAD_SOURCE_DIR}/config.h.in ${MAD_BINARY_DIR}/config.h) @@ -20,7 +20,6 @@ set(INCLUDES ${GNUTLS_INCLUDE_DIRS} ${DL_INCLUDE_DIR} ${READLINE_INCLUDE_DIR} -# ${KRB5_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ) diff --git a/src/mad-server.conf b/src/mad-server.conf index 58a5116..cca8e3a 100644 --- a/src/mad-server.conf +++ b/src/mad-server.conf @@ -50,6 +50,11 @@ UserManager { DeleteUserFromGroup "DELETE FROM usergroups WHERE uid = {UID} AND gid = {GID}" } } + + Krb5 { + Principal "root/admin" + Password "test" + } } Daemon test { diff --git a/src/mad-server.cpp b/src/mad-server.cpp index a0ca564..1700d1f 100644 --- a/src/mad-server.cpp +++ b/src/mad-server.cpp @@ -34,6 +34,7 @@ int main() { application.getModuleManager()->loadModule("UserDBBackendMysql"); application.getModuleManager()->loadModule("UserConfigBackendHome"); + application.getModuleManager()->loadModule("UserConfigBackendKrb5"); application.getConfigManager()->loadFile("mad-server.conf"); application.getConfigManager()->finish(); diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 1e8128b..1d036c9 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -40,6 +40,10 @@ if(MYSQL_FOUND) add_subdirectory(UserDBBackendMysql) endif(MYSQL_FOUND) +if(KRB5_FOUND) +add_subdirectory(UserConfigBackendKrb5) +endif(KRB5_FOUND) + SET(STATIC_MODULE_LOADERS "") SET(STATIC_MODULE_LIST "") diff --git a/src/modules/UserConfigBackendKrb5/CMakeLists.txt b/src/modules/UserConfigBackendKrb5/CMakeLists.txt new file mode 100644 index 0000000..1526af8 --- /dev/null +++ b/src/modules/UserConfigBackendKrb5/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${INCLUDES} ${KRB5_INCLUDE_DIRS}) + +mad_module(UserConfigBackendKrb5 + Module.cpp Module.h + UserConfigBackendKrb5.cpp UserConfigBackendKrb5.h +) + +mad_module_libraries(UserConfigBackendKrb5 ${KRB5_LIBRARIES}) diff --git a/src/modules/UserConfigBackendKrb5/Module.cpp b/src/modules/UserConfigBackendKrb5/Module.cpp new file mode 100644 index 0000000..ecfec56 --- /dev/null +++ b/src/modules/UserConfigBackendKrb5/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* UserConfigBackendKrb5_create(Mad::Common::Application *application) { + return new Mad::Modules::UserConfigBackendKrb5::Module(application); +} + +} diff --git a/src/modules/UserConfigBackendKrb5/Module.h b/src/modules/UserConfigBackendKrb5/Module.h new file mode 100644 index 0000000..b3d29a6 --- /dev/null +++ b/src/modules/UserConfigBackendKrb5/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_USERCONFIGBACKENDKRB5_MODULE_H_ +#define MAD_MODULES_USERCONFIGBACKENDKRB5_MODULE_H_ + +#include "UserConfigBackendKrb5.h" + +#include +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendKrb5 { + +class Module : public Common::Module { + private: + Common::Application *application; + + boost::shared_ptr backend; + + public: + Module(Common::Application *application0) : application(application0), backend(new UserConfigBackendKrb5(application)) { + application->getUserManager()->registerBackend(backend); + } + + virtual ~Module() { + application->getUserManager()->unregisterBackend(backend); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERCONFIGBACKENDKRB5_MODULE_H_ */ diff --git a/src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.cpp b/src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.cpp new file mode 100644 index 0000000..5a577ad --- /dev/null +++ b/src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.cpp @@ -0,0 +1,189 @@ +/* + * UserConfigBackendKrb5.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 "UserConfigBackendKrb5.h" +#include + +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendKrb5 { + +bool UserConfigBackendKrb5::connect() { + if(principal.empty()) { + application->log(Core::LoggerBase::USER, Core::LoggerBase::ERROR, "UserConfigBackendKrb5: no principal given"); + return false; + } + + if(realm.empty()) { + application->log(Core::LoggerBase::USER, Core::LoggerBase::ERROR, "UserConfigBackendKrb5: no realm given and no default realm available"); + return false; + } + + if(handle) { + kadm5_destroy(handle); + handle = 0; + } + + kadm5_config_params params; + params.realm = const_cast(realm.c_str()); + params.mask = KADM5_CONFIG_REALM; + + if(!server.empty()) { + params.admin_server = const_cast(server.c_str()); + params.mask |= KADM5_CONFIG_ADMIN_SERVER; + } + + std::string princ = principal; + if(princ.find('@') == std::string::npos) + princ += "@" + realm; + + if(!password.empty() && keytab.empty()) { + krb5_error_code err = kadm5_init_with_password(const_cast(princ.c_str()), const_cast(password.c_str()), + const_cast(KADM5_ADMIN_SERVICE), ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, 0, &handle); + + if(err) { + application->logf(Core::LoggerBase::USER, Core::LoggerBase::ERROR, "kadm5_init_with_password: %s", std::strerror(err)); + return false; + } + } + else { + char *keytabName = 0; + if(!keytab.empty()) + keytabName = const_cast(keytab.c_str()); + + krb5_error_code err = kadm5_init_with_skey(const_cast(princ.c_str()), keytabName, + const_cast(KADM5_ADMIN_SERVICE), ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, 0, &handle); + + if(err) { + application->logf(Core::LoggerBase::USER, Core::LoggerBase::ERROR, "kadm5_init_with_skey: %s", std::strerror(err)); + return false; + } + } + + application->log(Core::LoggerBase::USER, Core::LoggerBase::VERBOSE, "Connected to kerberos admin server."); + return true; +} + +bool UserConfigBackendKrb5::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(!entry[0].getKey().matches("UserManager")) + return false; + + if(entry[1].empty()) + return true; + + if(!entry[1].getKey().matches("Krb5")) + return false; + + if(entry[2].getKey().matches("Realm")) { + if(entry[3].empty()) + realm = entry[2][0]; + } + else if(entry[2].getKey().matches("Principal")) { + if(entry[3].empty()) + principal = entry[2][0]; + } + else if(entry[2].getKey().matches("Server")) { + if(entry[3].empty()) + server = entry[2][0]; + } + else if(entry[2].getKey().matches("Password")) { + if(entry[3].empty()) + password = entry[2][0]; + } + else if(entry[2].getKey().matches("Keytab")) { + if(entry[3].empty()) + keytab = entry[2][0]; + } + else if(!entry[2].empty()) + return false; + + return true; +} + + +void UserConfigBackendKrb5::checkUserInfo(const Common::UserInfo &userInfo) throw(Core::Exception) { + if(std::strcspn(userInfo.getUsername().c_str(), "/@") != userInfo.getUsername().length()) + throw Core::Exception(Core::Exception::INVALID_INPUT); +} + +void UserConfigBackendKrb5::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + std::string princStr = userInfo.getUsername() + "@" + realm; + + kadm5_principal_ent_rec princ; + + krb5_error_code err = krb5_parse_name(context, princStr.c_str(), &princ.principal); + if(err) + throw Core::Exception("krb5_parse_name", Core::Exception::INTERNAL_ERRNO, err); + + princ.attributes = KRB5_KDB_DISALLOW_ALL_TIX; + + char dummybuf[128]; + for(int i = 0; i < 128; ++i) + dummybuf[i] = (i+1)%128; + + err = kadm5_create_principal(handle, &princ, KADM5_PRINCIPAL|KADM5_ATTRIBUTES, dummybuf); + if(err) { + krb5_free_principal(context, princ.principal); + throw Core::Exception("kadm5_create_principal", Core::Exception::INTERNAL_ERRNO, err); + } + + err = kadm5_randkey_principal(handle, princ.principal, 0, 0); + if(err) { + krb5_free_principal(context, princ.principal); + throw Core::Exception("kadm5_randkey_principal", Core::Exception::INTERNAL_ERRNO, err); + } + + princ.attributes = 0; + err = kadm5_modify_principal(handle, &princ, KADM5_ATTRIBUTES); + + krb5_free_principal(context, princ.principal); + + if(err) + throw Core::Exception("kadm5_modify_principal", Core::Exception::INTERNAL_ERRNO, err); +} + +void UserConfigBackendKrb5::updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception) { + if(oldUserInfo.getUsername() == userInfo.getUsername()) + return; + + deleteUser(oldUserInfo); + addUser(userInfo); +} + +void UserConfigBackendKrb5::deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + std::string princStr = userInfo.getUsername() + "@" + realm; + krb5_principal princ; + + krb5_error_code err = krb5_parse_name(context, princStr.c_str(), &princ); + if(err) + throw Core::Exception("krb5_parse_name", Core::Exception::INTERNAL_ERRNO, err); + + /*err = */kadm5_delete_principal(handle, princ); + + krb5_free_principal(context, princ); + + //if(err) + // throw Core::Exception("kadm5_delete_principal", Core::Exception::INTERNAL_ERRNO, err); +} + +} +} +} diff --git a/src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.h b/src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.h new file mode 100644 index 0000000..afb7663 --- /dev/null +++ b/src/modules/UserConfigBackendKrb5/UserConfigBackendKrb5.h @@ -0,0 +1,97 @@ +/* + * UserConfigBackendKrb5.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_USERCONFIGBACKENDKRB5_USERCONFIGBACKENDKRB5_H_ +#define MAD_MODULES_USERCONFIGBACKENDKRB5_USERCONFIGBACKENDKRB5_H_ + +#include +#include + +#include +#include + +#define USE_KADM5_API_VERSION 2 +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendKrb5 { + +class UserConfigBackendKrb5 : public Common::UserConfigBackend, private Core::Configurable, private boost::noncopyable { + private: + Common::Application *application; + + std::string realm, principal, server; + std::string password, keytab; + + krb5_context context; + void *handle; + + bool connect(); + + protected: + virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool handled); + + virtual void configFinished() { + connect(); + } + + virtual void checkUserInfo(const Common::UserInfo &userInfo) throw(Core::Exception); + + 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: + UserConfigBackendKrb5(Common::Application *application0) : application(application0), handle(0) { + krb5_error_code err = krb5_init_context(&context); + if(err) { + context = 0; + return; + } + + char *defaultRealm; + + krb5_get_default_realm(context, &defaultRealm); + if(defaultRealm) { + realm = defaultRealm; + free(defaultRealm); + } + + application->getConfigManager()->registerConfigurable(this); + } + + virtual ~UserConfigBackendKrb5() { + if(!context) + return; + + application->getConfigManager()->unregisterConfigurable(this); + + if(handle) + kadm5_destroy(handle); + + krb5_free_context(context); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERCONFIGBACKENDKRB5_USERCONFIGBACKENDKRB5_H_ */ -- cgit v1.2.3