]> granicus.if.org Git - icinga2/commitdiff
Implemented message-based authorisation checks.
authorGunnar Beutner <gunnar.beutner@netways.de>
Wed, 9 May 2012 08:15:51 +0000 (10:15 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Wed, 9 May 2012 08:16:31 +0000 (10:16 +0200)
24 files changed:
Makefile.am
base/base.vcxproj
base/configcollection.cpp
base/configcollection.h
base/confighive.h
base/configobject.cpp
base/configobject.h
base/utility.cpp
base/utility.h
components/configfile/configfilecomponent.cpp
components/configrpc/configrpccomponent.cpp
components/configrpc/configrpccomponent.h
components/discovery/discoverycomponent.cpp
components/discovery/discoverycomponent.h
configure.ac
icinga-app/icinga1.conf
icinga-app/icinga2.conf
icinga-app/icinga3.conf
icinga.sln
icinga/icingaapplication.cpp
mmatch/Makefile.am [new file with mode: 0644]
mmatch/mmatch.c [new file with mode: 0644]
mmatch/mmatch.h [new file with mode: 0644]
mmatch/mmatch.vcxproj [new file with mode: 0644]

index ac6bea37f6c5387280e099f4a108f9b26a7b1109..bf5f101b0edbeaad9b12d5cbecd7fb6684cf3ad3 100644 (file)
@@ -2,6 +2,7 @@
 ## Created by Anjuta
 
 SUBDIRS = ltdl \
+       mmatch \
        base \
        cJSON \
        jsonrpc \
index 50b13abfad1ea4358815919ac5dac61155b1d677..19037d4f6858392f0e82fde4deaebf06a555ec4d 100644 (file)
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
-  <PropertyGroup />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <IncludePath>$(SolutionDir)\mmatch;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <IncludePath>$(SolutionDir)\mmatch;$(IncludePath)</IncludePath>
+  </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <PrecompiledHeader>
index a4c0d640d4d76497055e9d2b64915d9c4e16cfa8..585e0b47f3093b27feac6d0d18733c280a8a0076 100644 (file)
@@ -38,14 +38,7 @@ void ConfigCollection::AddObject(const ConfigObject::Ptr& object)
        RemoveObject(object);
 
        Objects[object->GetName()] = object;
-
-       EventArgs ea;
-       ea.Source = object;
-       OnObjectCreated(ea);
-
-       ConfigHive::Ptr hive = m_Hive.lock();
-       if (hive)
-               hive->OnObjectCreated(ea);
+       object->Commit();
 }
 
 /**
index 6dc1a66ba4ae57af29a9a8b85f2c0189d8c8b1e5..989672de92283158095c74f29e6ff3208b52683f 100644 (file)
@@ -28,9 +28,8 @@ public:
 
        void ForEachObject(function<int (const EventArgs&)> callback);
 
-       Event<EventArgs> OnObjectCreated;
+       Event<EventArgs> OnObjectCommitted;
        Event<EventArgs> OnObjectRemoved;
-       Event<PropertyChangedEventArgs> OnPropertyChanged;
 };
 
 }
index 52701ebfe6e8ee078a36653ad1b00abb1e4a28be..b0c89ddefab9c64f9c1a9ce7dcf328425e18cb34 100644 (file)
@@ -23,9 +23,8 @@ public:
        void ForEachObject(const string& type,
            function<int (const EventArgs&)> callback);
 
-       Event<EventArgs> OnObjectCreated;
+       Event<EventArgs> OnObjectCommitted;
        Event<EventArgs> OnObjectRemoved;
-       Event<PropertyChangedEventArgs> OnPropertyChanged;
 };
 
 }
index c0dfbe96e0e126eaaae6847739d555980339fa5b..e34e325201ad43eef5a7082045839e8f13840132 100644 (file)
@@ -30,7 +30,6 @@ void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive)
                throw InvalidArgumentException("Config object already has a parent hive.");
 
        m_Hive = hive;
-       OnPropertyChanged += bind_weak(&ConfigObject::PropertyChangedHandler, shared_from_this());
 }
 
 /**
@@ -118,21 +117,19 @@ bool ConfigObject::GetReplicated(void) const
 }
 
 /**
- * PropertyChangedHandler
+ * Commit
  *
  * Handles changed properties by propagating them to the hive
  * and collection this object is contained in.
  *
- * @param dpcea The event arguments.
- * @returns 0.
  */
-int ConfigObject::PropertyChangedHandler(const PropertyChangedEventArgs& dpcea)
+void ConfigObject::Commit(void)
 {
        ConfigHive::Ptr hive = m_Hive.lock();
        if (hive) {
-               hive->GetCollection(m_Type)->OnPropertyChanged(dpcea);
-               hive->OnPropertyChanged(dpcea);
+               EventArgs ea;
+               ea.Source = shared_from_this();
+               hive->GetCollection(m_Type)->OnObjectCommitted(ea);
+               hive->OnObjectCommitted(ea);
        }
-
-       return 0;
 }
index 1caee2eb3ab706651eecfbabf8c44bf970b2517b..b8aae2a10ec65d3838298d8ad37d4b4a09cf1306 100644 (file)
@@ -17,8 +17,6 @@ private:
        string m_Type;
        bool m_Replicated;
 
-       int PropertyChangedHandler(const PropertyChangedEventArgs& dpcea);
-
 public:
        typedef shared_ptr<ConfigObject> Ptr;
        typedef weak_ptr<ConfigObject> WeakPtr;
@@ -36,6 +34,8 @@ public:
 
        void SetReplicated(bool replicated);
        bool GetReplicated(void) const;
+
+       void Commit(void);
 };
 
 }
index 4136f81f05fc2bdc51c9a9d5593129ca2b908a1e..a2a8111f7634e78702a47200f75a1aca5c943312 100644 (file)
@@ -1,4 +1,5 @@
 #include "i2-base.h"
+#include <mmatch.h>
 
 using namespace icinga;
 
@@ -137,3 +138,8 @@ shared_ptr<X509> Utility::GetX509Certificate(string pemfile)
 
        return shared_ptr<X509>(cert, X509_free);
 }
+
+bool Utility::Match(string pattern, string text)
+{
+       return (match(pattern.c_str(), text.c_str()) != 0);
+}
index ef95d885f019f1be300c18e5dbe9e93f0c8e40a5..715722b5aa23175e893b34f21d417bef607e8b4a 100644 (file)
@@ -47,6 +47,8 @@ public:
        static shared_ptr<SSL_CTX> MakeSSLContext(string pubkey, string privkey, string cakey);
        static string GetCertificateCN(const shared_ptr<X509>& certificate);
        static shared_ptr<X509> GetX509Certificate(string pemfile);
+
+       static bool Match(string pattern, string text);
 };
 
 }
index 4406e6e8c6a4dae6cbf67903231acd92be39a3a1..c950048249587e2c7d7771ac21b002ce76801361 100644 (file)
@@ -55,13 +55,23 @@ void ConfigFileComponent::Start(void)
 
                        for (cJSON *property = object->child; property != NULL; property = property->next) {
                                string key = property->string;
+                               
+                               if (property->type == cJSON_String) {
+                                       string value = property->valuestring;
 
-                               if (property->type != cJSON_String)
-                                       continue;
+                                       cfgobj->SetPropertyString(key, value);
+                               } else if (property->type == cJSON_Array) {
+                                       Dictionary::Ptr items = make_shared<Dictionary>();
 
-                               string value = property->valuestring;
+                                       for (cJSON *item = property->child; item != NULL; item = item->next) {
+                                               if (item->type != cJSON_String)
+                                                       continue;
 
-                               cfgobj->SetPropertyString(key, value);
+                                               items->AddUnnamedPropertyString(item->valuestring);
+                                       }
+
+                                       cfgobj->SetPropertyDictionary(key, items);
+                               }
                        }
 
                        GetApplication()->GetConfigHive()->AddObject(cfgobj);
index 20a3fccfe7cf42bbaed2e509744c74630418fe81..1d67c6300a924af278608ee9e11d87b98377f51a 100644 (file)
@@ -19,24 +19,20 @@ void ConfigRpcComponent::Start(void)
                m_ConfigRpcEndpoint->RegisterMethodHandler("config::FetchObjects",
                    bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this()));
 
-               configHive->OnObjectCreated += bind_weak(&ConfigRpcComponent::LocalObjectCreatedHandler, shared_from_this());
+               configHive->OnObjectCommitted += bind_weak(&ConfigRpcComponent::LocalObjectCommittedHandler, shared_from_this());
                configHive->OnObjectRemoved += bind_weak(&ConfigRpcComponent::LocalObjectRemovedHandler, shared_from_this());
-               configHive->OnPropertyChanged += bind_weak(&ConfigRpcComponent::LocalPropertyChangedHandler, shared_from_this());
 
-               m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectCreated");
+               m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectCommitted");
                m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectRemoved");
-               m_ConfigRpcEndpoint->RegisterMethodSource("config::PropertyChanged");
        }
 
        endpointManager->OnNewEndpoint += bind_weak(&ConfigRpcComponent::NewEndpointHandler, shared_from_this());
 
        m_ConfigRpcEndpoint->RegisterMethodSource("config::FetchObjects");
-       m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCreated",
-           bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
+       m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCommitted",
+           bind_weak(&ConfigRpcComponent::RemoteObjectCommittedHandler, shared_from_this()));
        m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectRemoved",
            bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this()));
-       m_ConfigRpcEndpoint->RegisterMethodHandler("config::PropertyChanged",
-           bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
 
        endpointManager->RegisterEndpoint(m_ConfigRpcEndpoint);
 }
@@ -115,7 +111,7 @@ int ConfigRpcComponent::FetchObjectsHandler(const NewRequestEventArgs& ea)
        return 0;
 }
 
-int ConfigRpcComponent::LocalObjectCreatedHandler(const EventArgs& ea)
+int ConfigRpcComponent::LocalObjectCommittedHandler(const EventArgs& ea)
 {
        ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
        
@@ -141,32 +137,7 @@ int ConfigRpcComponent::LocalObjectRemovedHandler(const EventArgs& ea)
        return 0;
 }
 
-int ConfigRpcComponent::LocalPropertyChangedHandler(const PropertyChangedEventArgs& ea)
-{
-       ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
-       
-       if (!ShouldReplicateObject(object))
-               return 0;
-
-       JsonRpcRequest msg = MakeObjectMessage(object, "config::PropertyChanged", false);
-       Message params;
-       msg.SetParams(params);
-
-       Message properties;
-       params.GetDictionary()->SetPropertyDictionary("properties", properties.GetDictionary());
-
-       string value;
-       if (!object->GetPropertyString(ea.Property, &value))
-               return 0;
-
-       properties.GetDictionary()->SetPropertyString(ea.Property, value);
-
-       GetEndpointManager()->SendMulticastRequest(m_ConfigRpcEndpoint, msg);
-
-       return 0;
-}
-
-int ConfigRpcComponent::RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea)
+int ConfigRpcComponent::RemoteObjectCommittedHandler(const NewRequestEventArgs& ea)
 {
        JsonRpcRequest message = ea.Request;
        bool was_null = false;
index 27ce4bb3bba63dd5bf3dd0b252f76e8688a22e45..cdc4d8d96b9050f0b005070c103cd5fced8f80b0 100644 (file)
@@ -12,12 +12,11 @@ private:
        int NewEndpointHandler(const NewEndpointEventArgs& ea);
        int SessionEstablishedHandler(const EventArgs& ea);
 
-       int LocalObjectCreatedHandler(const EventArgs& ea);
+       int LocalObjectCommittedHandler(const EventArgs& ea);
        int LocalObjectRemovedHandler(const EventArgs& ea);
-       int LocalPropertyChangedHandler(const PropertyChangedEventArgs& ea);
 
        int FetchObjectsHandler(const NewRequestEventArgs& ea);
-       int RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea);
+       int RemoteObjectCommittedHandler(const NewRequestEventArgs& ea);
        int RemoteObjectRemovedHandler(const NewRequestEventArgs& ea);
 
        static JsonRpcRequest MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties);
index 4717f47bb1c4c44754f075f171c5406503545212..7dcb3405305de8b240e198b5bbf9d33df748ed90 100644 (file)
@@ -27,15 +27,16 @@ void DiscoveryComponent::Start(void)
        GetConfig()->GetPropertyInteger("broker", &isBroker);
        m_Broker = (isBroker != 0);
 
-       if (IsBroker()) {
+       m_DiscoveryEndpoint->RegisterMethodSource("discovery::RegisterComponent");
+       m_DiscoveryEndpoint->RegisterMethodHandler("discovery::RegisterComponent",
+               bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this()));
+
+       if (IsBroker())
                m_DiscoveryEndpoint->RegisterMethodSource("discovery::NewComponent");
-               m_DiscoveryEndpoint->RegisterMethodHandler("discovery::RegisterComponent",
-                       bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this()));
-       }
 
-       m_DiscoveryEndpoint->RegisterMethodSource("discovery::RegisterComponent");
        m_DiscoveryEndpoint->RegisterMethodHandler("discovery::NewComponent",
                bind_weak(&DiscoveryComponent::NewComponentMessageHandler, shared_from_this()));
+
        m_DiscoveryEndpoint->RegisterMethodHandler("discovery::Welcome",
                bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this()));
 
@@ -49,6 +50,9 @@ void DiscoveryComponent::Start(void)
        m_DiscoveryTimer->SetInterval(30);
        m_DiscoveryTimer->OnTimerExpired += bind_weak(&DiscoveryComponent::DiscoveryTimerHandler, shared_from_this());
        m_DiscoveryTimer->Start();
+
+       /* call the timer as soon as possible */
+       m_DiscoveryTimer->Reschedule(0);
 }
 
 /**
@@ -104,10 +108,8 @@ int DiscoveryComponent::NewEndpointHandler(const NewEndpointEventArgs& neea)
 {
        neea.Endpoint->OnIdentityChanged += bind_weak(&DiscoveryComponent::NewIdentityHandler, shared_from_this());
 
-       if (IsBroker()) {
-               /* accept discovery::RegisterComponent messages from any endpoint */
-               neea.Endpoint->RegisterMethodSource("discovery::RegisterComponent");
-       }
+       /* accept discovery::RegisterComponent messages from any endpoint */
+       neea.Endpoint->RegisterMethodSource("discovery::RegisterComponent");
 
        /* accept discovery::Welcome messages from any endpoint */
        neea.Endpoint->RegisterMethodSource("discovery::Welcome");
@@ -231,12 +233,6 @@ int DiscoveryComponent::NewIdentityHandler(const EventArgs& ea)
 
        GetEndpointManager()->ForEachEndpoint(bind(&DiscoveryComponent::CheckExistingEndpoint, this, endpoint, _1));
 
-       ConfigCollection::Ptr brokerCollection = GetApplication()->GetConfigHive()->GetCollection("broker");
-       if (brokerCollection->GetObject(identity)) {
-               /* accept discovery::NewComponent messages from brokers */
-               endpoint->RegisterMethodSource("discovery::NewComponent");
-       }
-
        // we assume the other component _always_ wants
        // discovery::RegisterComponent messages from us
        endpoint->RegisterMethodSink("discovery::RegisterComponent");
@@ -394,6 +390,30 @@ void DiscoveryComponent::SendDiscoveryMessage(string method, string identity, En
                GetEndpointManager()->SendMulticastRequest(m_DiscoveryEndpoint, request);
 }
 
+bool DiscoveryComponent::HasMessagePermission(Dictionary::Ptr roles, string messageType, string message)
+{
+       ConfigHive::Ptr configHive = GetApplication()->GetConfigHive();
+       ConfigCollection::Ptr roleCollection = configHive->GetCollection("role");
+
+       for (DictionaryIterator ip = roles->Begin(); ip != roles->End(); ip++) {
+               ConfigObject::Ptr role = roleCollection->GetObject(ip->second);
+
+               if (!role)
+                       continue;
+
+               Dictionary::Ptr permissions;
+               if (!role->GetPropertyDictionary(messageType, &permissions))
+                       continue;
+
+               for (DictionaryIterator is = permissions->Begin(); is != permissions->End(); is++) {
+                       if (Utility::Match(is->second.GetString(), message))
+                               return true;
+               }
+       }
+
+       return false;
+}
+
 /**
  * ProcessDiscoveryMessage
  *
@@ -402,8 +422,9 @@ void DiscoveryComponent::SendDiscoveryMessage(string method, string identity, En
  *
  * @param identity The authorative identity of the component.
  * @param message The discovery message.
+ * @param trusted Whether the message comes from a trusted source (i.e. a broker).
  */
-void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessage message)
+void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessage message, bool trusted)
 {
        /* ignore discovery messages that are about ourselves */
        if (identity == GetEndpointManager()->GetIdentity())
@@ -416,14 +437,20 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa
        message.GetNode(&info->Node);
        message.GetService(&info->Service);
 
+       ConfigHive::Ptr configHive = GetApplication()->GetConfigHive();
+       ConfigCollection::Ptr endpointCollection = configHive->GetCollection("endpoint");
+
+       ConfigObject::Ptr endpointConfig = endpointCollection->GetObject(identity);
+       Dictionary::Ptr roles;
+       if (endpointConfig)
+               endpointConfig->GetPropertyDictionary("roles", &roles);
+
        Message provides;
        if (message.GetProvides(&provides)) {
                DictionaryIterator i;
                for (i = provides.GetDictionary()->Begin(); i != provides.GetDictionary()->End(); i++) {
-                       if (IsBroker()) {
-                               /* TODO: Add authorisation checks here */
-                       }
-                       info->PublishedMethods.insert(i->second);
+                       if (trusted || HasMessagePermission(roles, "publish", i->second))
+                               info->PublishedMethods.insert(i->second);
                }
        }
 
@@ -431,16 +458,14 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa
        if (message.GetSubscribes(&subscribes)) {
                DictionaryIterator i;
                for (i = subscribes.GetDictionary()->Begin(); i != subscribes.GetDictionary()->End(); i++) {
-                       if (IsBroker()) {
-                               /* TODO: Add authorisation checks here */
-                       }
-                       info->SubscribedMethods.insert(i->second);
+                       if (trusted || HasMessagePermission(roles, "subscribe", i->second))
+                               info->SubscribedMethods.insert(i->second);
                }
        }
 
        map<string, ComponentDiscoveryInfo::Ptr>::iterator i;
 
-       i  = m_Components.find(identity);
+       i = m_Components.find(identity);
 
        if (i != m_Components.end())
                m_Components.erase(i);
@@ -472,7 +497,7 @@ int DiscoveryComponent::NewComponentMessageHandler(const NewRequestEventArgs& nr
        if (!message.GetIdentity(&identity))
                return 0;
 
-       ProcessDiscoveryMessage(identity, message);
+       ProcessDiscoveryMessage(identity, message, true);
        return 0;
 }
 
@@ -486,45 +511,36 @@ int DiscoveryComponent::NewComponentMessageHandler(const NewRequestEventArgs& nr
  */
 int DiscoveryComponent::RegisterComponentMessageHandler(const NewRequestEventArgs& nrea)
 {
-       /* ignore discovery::RegisterComponent messages when we're not a broker */
-       if (!IsBroker())
-               return 0;
-
        DiscoveryMessage message;
        nrea.Request.GetParams(&message);
-       ProcessDiscoveryMessage(nrea.Sender->GetIdentity(), message);
+       ProcessDiscoveryMessage(nrea.Sender->GetIdentity(), message, false);
 
        return 0;
 }
 
 /**
- * BrokerConfigHandler
+ * EndpointConfigHandler
  *
- * Processes "broker" config objects.
+ * Processes "endpoint" config objects.
  *
  * @param ea Event arguments for the new config object.
  * @returns 0
  */
-int DiscoveryComponent::BrokerConfigHandler(const EventArgs& ea)
+int DiscoveryComponent::EndpointConfigHandler(const EventArgs& ea)
 {
        ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
 
        EndpointManager::Ptr endpointManager = GetEndpointManager();
 
-       /* Check if we're already connected to this broker. */
+       /* Check if we're already connected to this endpoint. */
        if (endpointManager->GetEndpointByIdentity(object->GetName()))
                return 0;
 
-       string node;
-       if (!object->GetPropertyString("node", &node))
-               throw InvalidArgumentException("'node' property required for 'broker' config object.");
-
-       string service;
-       if (!object->GetPropertyString("service", &service))
-               throw InvalidArgumentException("'service' property required for 'broker' config object.");
-
-       /* reconnect to this broker */
-       endpointManager->AddConnection(node, service);
+       string node, service;
+       if (object->GetPropertyString("node", &node) && object->GetPropertyString("service", &service)) {
+               /* reconnect to this endpoint */
+               endpointManager->AddConnection(node, service);
+       }
 
        return 0;
 }
@@ -545,9 +561,9 @@ int DiscoveryComponent::DiscoveryTimerHandler(const TimerEventArgs& tea)
        time_t now;
        time(&now);
 
-       /* check whether we have to reconnect to one of our upstream brokers */
-       ConfigCollection::Ptr brokerCollection = GetApplication()->GetConfigHive()->GetCollection("broker");
-       brokerCollection->ForEachObject(bind(&DiscoveryComponent::BrokerConfigHandler, this, _1));
+       /* check whether we have to reconnect to one of our upstream endpoints */
+       ConfigCollection::Ptr endpointCollection = GetApplication()->GetConfigHive()->GetCollection("endpoint");
+       endpointCollection->ForEachObject(bind(&DiscoveryComponent::EndpointConfigHandler, this, _1));
 
        map<string, ComponentDiscoveryInfo::Ptr>::iterator i;
        for (i = m_Components.begin(); i != m_Components.end(); ) {
index a00b90bff75fc33658f9b81d3f054f920987c827..77535ebad5f5d8a3b9176f1b00b84851f40fc3fd 100644 (file)
@@ -36,7 +36,7 @@ private:
        int WelcomeMessageHandler(const NewRequestEventArgs& nrea);
 
        void SendDiscoveryMessage(string method, string identity, Endpoint::Ptr recipient);
-       void ProcessDiscoveryMessage(string identity, DiscoveryMessage message);
+       void ProcessDiscoveryMessage(string identity, DiscoveryMessage message, bool trusted);
 
        bool GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const;
 
@@ -51,7 +51,9 @@ private:
 
        void FinishDiscoverySetup(Endpoint::Ptr endpoint);
 
-       int BrokerConfigHandler(const EventArgs& ea);
+       int EndpointConfigHandler(const EventArgs& ea);
+
+       bool HasMessagePermission(Dictionary::Ptr roles, string messageType, string message);
 
        static const int RegistrationTTL = 300;
 
index 2f3c619d8e9ea1b0315a80231a7da9e517080213..c5b681897155b4e2a0fcacd5dab5e0187e865d61 100644 (file)
@@ -56,5 +56,5 @@ components/discovery/Makefile
 icinga/Makefile
 icinga-app/Makefile
 jsonrpc/Makefile
-
+mmatch/Makefile
 ])
index 17d963f91dd87346294a66df125fbeb6bdc9405c..601ab601f6ce0639c652a4205bfaef85041b755e 100644 (file)
@@ -5,7 +5,7 @@
                        "privkey": "icinga-c1.key",
                        "pubkey": "icinga-c1.crt",
                        "cakey": "ca.crt",
-                       "node": "10.0.10.3",
+                       "node": "10.0.10.14",
                        "service": "7777"
                }
        },
@@ -16,5 +16,8 @@
        },
        "host": {
                "localhost": { "node": "127.0.0.1" }
+       },
+       "include": {
+               "permissions.conf": { "test": [ "hello", "world" ] }
        }
 }
\ No newline at end of file
index 46d84d8e0e0c9b32de36a8e4378335763c499aa5..c457b86da1aec6e57d1fe78b677a13e42a35cd70 100644 (file)
                "demo": { "replicate": "0" },
                "discovery": { "replicate": "0", "broker": "0" }
        },
-       "broker": {
-               "icinga-c1": { "replicate": "0", "node": "10.0.10.3", "service": "7777" }
+       "endpoint": {
+               "icinga-c1": {
+                       "replicate": "0",
+                       "node": "10.0.10.14",
+                       "service": "7777",
+                       "roles": [ "broker", "demo" ]
+               }
+       },
+       "role": {
+               "broker": {
+                       "publish": [ "discovery::NewComponent" ]
+               },
+               "demo": {
+                       "publish": [ "demo::*" ],
+                       "subscribe": [ "demo::*" ]
+               }
        }
 }
\ No newline at end of file
index ed9894d89f2038b80152a9e69a569b1d3fca0b1e..c6af6127300b87f211bf3be4e53bbe4a6ceae40f 100644 (file)
                "demo": { "replicate": "0" },
                "discovery": { "replicate": "0", "broker": "0" }
        },
-       "broker": {
-               "icinga-c1": { "replicate": "0", "node": "10.0.10.3", "service": "7777" }
+       "endpoint": {
+               "icinga-c1": {
+                       "replicate": "0",
+                       "node": "10.0.10.14",
+                       "service": "7777",
+                       "roles": [ "broker", "demo" ]
+               }
+       },
+       "role": {
+               "broker": {
+                       "publish": [ "discovery::NewComponent" ]
+               },
+               "demo": {
+                       "publish": [ "demo::*" ],
+                       "subscribe": [ "demo::*" ]
+               }
        }
 }
\ No newline at end of file
index e5f25da2f01bf57b1efaa3122bf52187dbe52d76..21ee272eea9ce6a77e36e698fb328aaa4f8f2271 100644 (file)
@@ -2,6 +2,9 @@
 Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual C++ Express 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "base\base.vcxproj", "{9C92DA90-FD53-43A9-A244-90F2E8AF9677}"
+       ProjectSection(ProjectDependencies) = postProject
+               {19CBCE06-3F5C-479A-BD75-E2AB6215D345} = {19CBCE06-3F5C-479A-BD75-E2AB6215D345}
+       EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsonrpc", "jsonrpc\jsonrpc.vcxproj", "{8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}"
        ProjectSection(ProjectDependencies) = postProject
@@ -46,6 +49,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "discovery", "components\dis
                {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}
        EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mmatch", "mmatch\mmatch.vcxproj", "{19CBCE06-3F5C-479A-BD75-E2AB6215D345}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Win32 = Debug|Win32
@@ -88,6 +93,10 @@ Global
                {EAD41628-BB96-4F99-9070-8A9676801295}.Debug|Win32.Build.0 = Debug|Win32
                {EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.ActiveCfg = Release|Win32
                {EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.Build.0 = Release|Win32
+               {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.ActiveCfg = Debug|Win32
+               {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.Build.0 = Debug|Win32
+               {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.ActiveCfg = Release|Win32
+               {19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.Build.0 = Release|Win32
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
index 8fd2f318de45cf8d0c1ddb506c0227845eadc13e..1419039c688aa1b83f4542d34ccb5fd4a4f48663 100644 (file)
@@ -30,14 +30,14 @@ int IcingaApplication::Main(const vector<string>& args)
        /* register handler for 'icinga' config objects */
        ConfigCollection::Ptr icingaCollection = GetConfigHive()->GetCollection("icinga");
        function<int (const EventArgs&)> NewIcingaConfigHandler = bind_weak(&IcingaApplication::NewIcingaConfigHandler, shared_from_this());
-       icingaCollection->OnObjectCreated += NewIcingaConfigHandler;
+       icingaCollection->OnObjectCommitted += NewIcingaConfigHandler;
        icingaCollection->ForEachObject(NewIcingaConfigHandler);
        icingaCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedIcingaConfigHandler, shared_from_this());
 
        /* register handler for 'component' config objects */
        ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component");
        function<int (const EventArgs&)> NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this());
-       componentCollection->OnObjectCreated += NewComponentHandler;
+       componentCollection->OnObjectCommitted += NewComponentHandler;
        componentCollection->ForEachObject(NewComponentHandler);
        componentCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this());
 
diff --git a/mmatch/Makefile.am b/mmatch/Makefile.am
new file mode 100644 (file)
index 0000000..453ad36
--- /dev/null
@@ -0,0 +1,9 @@
+## Process this file with automake to produce Makefile.in
+
+
+noinst_LTLIBRARIES =  \
+       libmmatch.la
+
+libmmatch_la_SOURCES =  \
+       mmatch.c \
+       mmatch.h
diff --git a/mmatch/mmatch.c b/mmatch/mmatch.c
new file mode 100644 (file)
index 0000000..10b8ce3
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * IRC - Internet Relay Chat, common/match.c
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: Match.cpp,v 1.2 2005/08/15 10:08:50 shroud23 Exp $
+ */
+
+#include <ctype.h>
+#include "mmatch.h"
+
+#define ToLower tolower
+
+/*
+ * mmatch()
+ *
+ * Written by Run (carlo@runaway.xs4all.nl), 25-10-96
+ *
+ *
+ * From: Carlo Wood <carlo@runaway.xs4all.nl>
+ * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
+ * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
+ * To: coder-com@mail.undernet.org (coder committee)
+ * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
+ *
+ * We need a new function `mmatch(const char *old_mask, const char *new_mask)'
+ * which returns `true' likewise the current `match' (start with copying it),
+ * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
+ * as follows:  a '*' in `new_mask' does not match a '?' in `old_mask' and
+ * a '?' in `new_mask' does not match a '\?' in `old_mask'.
+ * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
+ * And last but not least, '\?' and '\*' in `new_mask' now become one character.
+ */
+
+int mmatch(const char *old_mask, const char *new_mask)
+{
+  const char *m = old_mask;
+  const char *n = new_mask;
+  const char *ma = m;
+  const char *na = n;
+  int wild = 0;
+  int mq = 0, nq = 0;
+
+  while (1)
+  {
+    if (*m == '*')
+    {
+      while (*m == '*')
+        m++;
+      wild = 1;
+      ma = m;
+      na = n;
+    }
+
+    if (!*m)
+    {
+      if (!*n)
+        return 0;
+      for (m--; (m > old_mask) && (*m == '?'); m--)
+        ;
+      if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
+        return 0;
+      if (!wild)
+        return 1;
+      m = ma;
+
+      /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
+      if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
+        ++na;
+
+      n = ++na;
+    }
+    else if (!*n)
+    {
+      while (*m == '*')
+        m++;
+      return (*m != 0);
+    }
+    if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+    {
+      m++;
+      mq = 1;
+    }
+    else
+      mq = 0;
+
+    /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
+    if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
+    {
+      n++;
+      nq = 1;
+    }
+    else
+      nq = 0;
+
+/*
+ * This `if' has been changed compared to match() to do the following:
+ * Match when:
+ *   old (m)         new (n)         boolean expression
+ *    *               any             (*m == '*' && !mq) ||
+ *    ?               any except '*'  (*m == '?' && !mq && (*n != '*' || nq)) ||
+ * any except * or ?  same as m       (!((*m == '*' || *m == '?') && !mq) &&
+ *                                      ToLower(*m) == ToLower(*n) &&
+ *                                        !((mq && !nq) || (!mq && nq)))
+ *
+ * Here `any' also includes \* and \? !
+ *
+ * After reworking the boolean expressions, we get:
+ * (Optimized to use boolean shortcircuits, with most frequently occuring
+ *  cases upfront (which took 2 hours!)).
+ */
+    if ((*m == '*' && !mq) ||
+        ((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
+        (*m == '?' && !mq && (*n != '*' || nq)))
+    {
+      if (*m)
+        m++;
+      if (*n)
+        n++;
+    }
+    else
+    {
+      if (!wild)
+        return 1;
+      m = ma;
+
+      /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
+      if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
+        ++na;
+
+      n = ++na;
+    }
+  }
+}
+
+/*
+ * Compare if a given string (name) matches the given
+ * mask (which can contain wild cards: '*' - match any
+ * number of chars, '?' - match any single character.
+ *
+ * return  0, if match
+ *         1, if no match
+ */
+
+/*
+ * match
+ *
+ * Rewritten by Andrea Cocito (Nemesi), November 1998.
+ *
+ */
+
+/****************** Nemesi's match() ***************/
+
+int match(const char *mask, const char *string)
+{
+  const char *m = mask, *s = string;
+  char ch;
+  const char *bm, *bs;          /* Will be reg anyway on a decent CPU/compiler */
+
+  /* Process the "head" of the mask, if any */
+  while ((ch = *m++) && (ch != '*'))
+    switch (ch)
+    {
+      case '\\':
+        if (*m == '?' || *m == '*')
+          ch = *m++;
+      default:
+        if (ToLower(*s) != ToLower(ch))
+          return 1;
+      case '?':
+        if (!*s++)
+          return 1;
+    };
+  if (!ch)
+    return *s;
+
+  /* We got a star: quickly find if/where we match the next char */
+got_star:
+  bm = m;                       /* Next try rollback here */
+  while ((ch = *m++))
+    switch (ch)
+    {
+      case '?':
+        if (!*s++)
+          return 1;
+      case '*':
+        bm = m;
+        continue;               /* while */
+      case '\\':
+        if (*m == '?' || *m == '*')
+          ch = *m++;
+      default:
+        goto break_while;       /* C is structured ? */
+    };
+break_while:
+  if (!ch)
+    return 0;                   /* mask ends with '*', we got it */
+  ch = ToLower(ch);
+  if (!*s)                     /* String is already empty, don't continue */
+    return 1;                  /* This fixes the #quakenet access denied bug */
+  while (ToLower(*s++) != ch)
+    if (!*s)
+      return 1;
+  bs = s;                       /* Next try start from here */
+
+  /* Check the rest of the "chunk" */
+  while ((ch = *m++))
+  {
+    switch (ch)
+    {
+      case '*':
+        goto got_star;
+      case '\\':
+        if (*m == '?' || *m == '*')
+          ch = *m++;
+      default:
+        if (ToLower(*s) != ToLower(ch))
+        {
+          /* If we've run out of string, give up */
+          if (!*bs)
+            return 1;
+          m = bm;
+          s = bs;
+          goto got_star;
+        };
+      case '?':
+        if (!*s++)
+          return 1;
+    };
+  };
+  if (*s)
+  {
+    m = bm;
+    s = bs;
+    goto got_star;
+  };
+  return 0;
+}
+
+/*
+ * collapse()
+ * Collapse a pattern string into minimal components.
+ * This particular version is "in place", so that it changes the pattern
+ * which is to be reduced to a "minimal" size.
+ *
+ * (C) Carlo Wood - 6 Oct 1998
+ * Speedup rewrite by Andrea Cocito, December 1998.
+ * Note that this new optimized alghoritm can *only* work in place.
+ */
+
+char *collapse(char *mask)
+{
+  int star = 0;
+  char *m = mask;
+  char *b;
+
+  if (m)
+  {
+    do
+    {
+      if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
+      {
+        b = m;
+        do
+        {
+          if (*m == '*')
+            star = 1;
+          else
+          {
+            if (star && (*m != '?'))
+            {
+              *b++ = '*';
+              star = 0;
+            };
+            *b++ = *m;
+            if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+              *b++ = *++m;
+          };
+        }
+        while (*m++);
+        break;
+      }
+      else
+      {
+        if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+          m++;
+      };
+    }
+    while (*m++);
+  };
+  return mask;
+}
\ No newline at end of file
diff --git a/mmatch/mmatch.h b/mmatch/mmatch.h
new file mode 100644 (file)
index 0000000..3a48c20
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef MMATCH_H
+#define MMATCH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int mmatch(const char *old_mask, const char *new_mask);
+int match(const char *ma, const char *na);
+char *collapse(char *pattern);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* MMATCH_H */
diff --git a/mmatch/mmatch.vcxproj b/mmatch/mmatch.vcxproj
new file mode 100644 (file)
index 0000000..40d9905
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="mmatch.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="mmatch.h" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{19CBCE06-3F5C-479A-BD75-E2AB6215D345}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>mmatch</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file