Implemented message-based authorisation checks.

This commit is contained in:
Gunnar Beutner 2012-05-09 10:15:51 +02:00
parent 36eb5e1cf3
commit 18bffce0ed
24 changed files with 575 additions and 125 deletions

View File

@ -2,6 +2,7 @@
## Created by Anjuta
SUBDIRS = ltdl \
mmatch \
base \
cJSON \
jsonrpc \

View File

@ -93,7 +93,12 @@
<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>

View 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();
}
/**

View 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;
};
}

View 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;
};
}

View 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;
}

View 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);
};
}

View 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);
}

View 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);
};
}

View File

@ -56,12 +56,22 @@ void ConfigFileComponent::Start(void)
for (cJSON *property = object->child; property != NULL; property = property->next) {
string key = property->string;
if (property->type != cJSON_String)
continue;
if (property->type == cJSON_String) {
string value = property->valuestring;
string value = property->valuestring;
cfgobj->SetPropertyString(key, value);
} else if (property->type == cJSON_Array) {
Dictionary::Ptr items = make_shared<Dictionary>();
cfgobj->SetPropertyString(key, value);
for (cJSON *item = property->child; item != NULL; item = item->next) {
if (item->type != cJSON_String)
continue;
items->AddUnnamedPropertyString(item->valuestring);
}
cfgobj->SetPropertyDictionary(key, items);
}
}
GetApplication()->GetConfigHive()->AddObject(cfgobj);

View 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;

View 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);

View File

@ -27,15 +27,16 @@ void DiscoveryComponent::Start(void)
GetConfig()->GetPropertyInteger("broker", &isBroker);
m_Broker = (isBroker != 0);
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::RegisterComponent",
bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this()));
if (IsBroker())
m_DiscoveryEndpoint->RegisterMethodSource("discovery::NewComponent");
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(); ) {

View 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;

View File

@ -56,5 +56,5 @@ components/discovery/Makefile
icinga/Makefile
icinga-app/Makefile
jsonrpc/Makefile
mmatch/Makefile
])

View 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" ] }
}
}

View File

@ -14,7 +14,21 @@
"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::*" ]
}
}
}

View File

@ -14,7 +14,21 @@
"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::*" ]
}
}
}

View 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

View 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());

9
mmatch/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = \
libmmatch.la
libmmatch_la_SOURCES = \
mmatch.c \
mmatch.h

305
mmatch/mmatch.c Normal file
View File

@ -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;
}

16
mmatch/mmatch.h Normal file
View File

@ -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 */

80
mmatch/mmatch.vcxproj Normal file
View File

@ -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>