[icinga-checkins] icinga.org: icinga2/feature/livestatus-bygroup-7361: Validate configured TimePeriod ranges

git at icinga.org git at icinga.org
Sun Feb 15 17:04:27 CET 2015


Module: icinga2
Branch: feature/livestatus-bygroup-7361
Commit: 2ed78e82a803ced529e32dbce48b3a9435ca4432
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=2ed78e82a803ced529e32dbce48b3a9435ca4432

Author: Michael Friedrich <michael.friedrich at netways.de>
Date:   Thu Feb 12 09:12:55 2015 +0100

Validate configured TimePeriod ranges

Requires re-throwing the hidden exceptions inside the existing
timeperiod code and validating the configured time range
strings then.

fixes #7576

---

 lib/icinga/icinga-type.conf     |    2 ++
 lib/icinga/legacytimeperiod.cpp |   34 +++++++++++++++++++++++++++++-----
 lib/icinga/timeperiod.cpp       |   35 +++++++++++++++++++++++++++++++++++
 lib/icinga/timeperiod.hpp       |    2 ++
 4 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/lib/icinga/icinga-type.conf b/lib/icinga/icinga-type.conf
index 18d4c9f..175423f 100644
--- a/lib/icinga/icinga-type.conf
+++ b/lib/icinga/icinga-type.conf
@@ -179,6 +179,8 @@
 }
 
 %type TimePeriod %inherits CustomVarObject {
+	%validator "ValidateTimePeriodRanges",
+
 	%attribute %string "display_name",
 
 	%require "update",
diff --git a/lib/icinga/legacytimeperiod.cpp b/lib/icinga/legacytimeperiod.cpp
index 6e380ad..d78cc00 100644
--- a/lib/icinga/legacytimeperiod.cpp
+++ b/lib/icinga/legacytimeperiod.cpp
@@ -289,7 +289,11 @@ void LegacyTimePeriod::ParseTimeRange(const String& timerange, tm *begin, tm *en
 		String second = def.SubStr(pos + 1);
 		second.Trim();
 
-		ParseTimeSpec(first, begin, NULL, reference);
+		try {
+			ParseTimeSpec(first, begin, NULL, reference);
+		} catch (std::exception&) {
+			throw;
+		}
 
 		/* If the second definition starts with a number we need
 		 * to add the first word from the first definition, e.g.:
@@ -310,9 +314,17 @@ void LegacyTimePeriod::ParseTimeRange(const String& timerange, tm *begin, tm *en
 			second = first.SubStr(0, xpos + 1) + second;
 		}
 
-		ParseTimeSpec(second, NULL, end, reference);
+		try {
+			ParseTimeSpec(second, NULL, end, reference);
+		} catch (std::exception&) {
+			throw;
+		}
 	} else {
-		ParseTimeSpec(def, begin, end, reference);
+		try {
+			ParseTimeSpec(def, begin, end, reference);
+		} catch (std::exception&) {
+			throw;
+		}
 	}
 }
 
@@ -364,7 +376,13 @@ void LegacyTimePeriod::ProcessTimeRangeRaw(const String& timerange, tm *referenc
 Dictionary::Ptr LegacyTimePeriod::ProcessTimeRange(const String& timestamp, tm *reference)
 {
 	tm begin, end;
-	ProcessTimeRangeRaw(timestamp, reference, &begin, &end);
+
+	try {
+		ProcessTimeRangeRaw(timestamp, reference, &begin, &end);
+	} catch (std::exception&) {
+		throw;
+	}
+
 	Dictionary::Ptr segment = new Dictionary();
 	segment->Set("begin", (long)mktime(&begin));
 	segment->Set("end", (long)mktime(&end));
@@ -378,7 +396,13 @@ void LegacyTimePeriod::ProcessTimeRanges(const String& timeranges, tm *reference
 	boost::algorithm::split(ranges, timeranges, boost::is_any_of(","));
 
 	BOOST_FOREACH(const String& range, ranges) {
-		Dictionary::Ptr segment = ProcessTimeRange(range, reference);
+		Dictionary::Ptr segment;
+		try {
+			segment = ProcessTimeRange(range, reference);
+		} catch (std::exception&) {
+			throw;
+		}
+
 		if (segment->Get("begin") >= segment->Get("end"))
 			BOOST_THROW_EXCEPTION(std::invalid_argument("Time period segment ends before it begins"));
 
diff --git a/lib/icinga/timeperiod.cpp b/lib/icinga/timeperiod.cpp
index 985aa6f..e03e3a5 100644
--- a/lib/icinga/timeperiod.cpp
+++ b/lib/icinga/timeperiod.cpp
@@ -18,8 +18,10 @@
  ******************************************************************************/
 
 #include "icinga/timeperiod.hpp"
+#include "icinga/legacytimeperiod.hpp"
 #include "base/dynamictype.hpp"
 #include "base/objectlock.hpp"
+#include "base/exception.hpp"
 #include "base/logger.hpp"
 #include "base/timer.hpp"
 #include "base/utility.hpp"
@@ -28,6 +30,7 @@
 using namespace icinga;
 
 REGISTER_TYPE(TimePeriod);
+REGISTER_SCRIPTFUNCTION(ValidateTimePeriodRanges, &TimePeriod::ValidateRanges);
 
 static Timer::Ptr l_UpdateTimer;
 
@@ -297,3 +300,35 @@ void TimePeriod::Dump(void)
 
 	Log(LogDebug, "TimePeriod", "---");
 }
+
+void TimePeriod::ValidateRanges(const String& location, const TimePeriod::Ptr& object)
+{
+	Dictionary::Ptr ranges = object->GetRanges();
+
+	if (!ranges)
+		return;
+
+	/* create a fake time environment to validate the definitions */
+	time_t begin = Utility::GetTime();
+	time_t end = begin + 24 * 60 * 60;
+	tm reference = Utility::LocalTime(end);
+	tm begin_tm, end_tm;
+	Array::Ptr segments = new Array();
+
+	ObjectLock olock(ranges);
+	BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
+		try {
+			LegacyTimePeriod::ParseTimeSpec(kv.first, &begin_tm, &end_tm, &reference);
+		} catch (std::exception&) {
+			BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
+			    location + ": Invalid time specification.", object->GetDebugInfo()));
+		}
+
+		try {
+			LegacyTimePeriod::ProcessTimeRanges(kv.second, &reference, segments);
+		} catch (std::exception&) {
+			BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
+			    location + ": Invalid time range definition.", object->GetDebugInfo()));
+		}
+	}
+}
diff --git a/lib/icinga/timeperiod.hpp b/lib/icinga/timeperiod.hpp
index 037ba6f..81b3d2d 100644
--- a/lib/icinga/timeperiod.hpp
+++ b/lib/icinga/timeperiod.hpp
@@ -46,6 +46,8 @@ public:
 	bool IsInside(double ts) const;
 	double FindNextTransition(double begin);
 
+	static void ValidateRanges(const String& location, const TimePeriod::Ptr& object);
+
 private:
 	void AddSegment(double s, double end);
 	void AddSegment(const Dictionary::Ptr& segment);



More information about the icinga-checkins mailing list