]> granicus.if.org Git - icinga2/commitdiff
Validate configured TimePeriod ranges
authorMichael Friedrich <michael.friedrich@netways.de>
Thu, 12 Feb 2015 08:12:55 +0000 (09:12 +0100)
committerMichael Friedrich <michael.friedrich@netways.de>
Fri, 13 Feb 2015 16:10:58 +0000 (17:10 +0100)
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
lib/icinga/legacytimeperiod.cpp
lib/icinga/timeperiod.cpp
lib/icinga/timeperiod.hpp

index 18d4c9f85b944497decd2823518ebe84fa0e7b12..175423f813df7fded27f7f0057a12b092b590602 100644 (file)
 }
 
 %type TimePeriod %inherits CustomVarObject {
+       %validator "ValidateTimePeriodRanges",
+
        %attribute %string "display_name",
 
        %require "update",
index 6e380ad8c3fad706e88465bf6c2b607691f30953..d78cc00f4d4b3389e0641d8961d7bc1094710421 100644 (file)
@@ -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"));
 
index 985aa6f12853c8cfaec43bb56ce75bd0c11c568f..e03e3a5b3300066458c89bbdc5247af809d8b1e2 100644 (file)
  ******************************************************************************/
 
 #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()));
+               }
+       }
+}
index 037ba6f62d9cba307ddca98575ecebc48d5b7732..81b3d2de8e2db4ec9687a0929e72fce589463be5 100644 (file)
@@ -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);