mirror of https://github.com/Icinga/icinga2.git
parent
9a3326fe66
commit
d93bcedaad
|
@ -129,15 +129,15 @@ Object::Ptr Array::GetPrototype(void)
|
|||
|
||||
if (!prototype) {
|
||||
prototype = new Dictionary();
|
||||
prototype->Set("len", new Function(WrapFunction(ArrayLen)));
|
||||
prototype->Set("len", new Function(WrapFunction(ArrayLen), true));
|
||||
prototype->Set("set", new Function(WrapFunction(ArraySet)));
|
||||
prototype->Set("add", new Function(WrapFunction(ArrayAdd)));
|
||||
prototype->Set("remove", new Function(WrapFunction(ArrayRemove)));
|
||||
prototype->Set("contains", new Function(WrapFunction(ArrayContains)));
|
||||
prototype->Set("contains", new Function(WrapFunction(ArrayContains), true));
|
||||
prototype->Set("clear", new Function(WrapFunction(ArrayClear)));
|
||||
prototype->Set("sort", new Function(WrapFunction(ArraySort)));
|
||||
prototype->Set("clone", new Function(WrapFunction(ArrayClone)));
|
||||
prototype->Set("join", new Function(WrapFunction(ArrayJoin)));
|
||||
prototype->Set("sort", new Function(WrapFunction(ArraySort), true));
|
||||
prototype->Set("clone", new Function(WrapFunction(ArrayClone), true));
|
||||
prototype->Set("join", new Function(WrapFunction(ArrayJoin), true));
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
@ -38,7 +38,7 @@ Object::Ptr Boolean::GetPrototype(void)
|
|||
|
||||
if (!prototype) {
|
||||
prototype = new Dictionary();
|
||||
prototype->Set("to_string", new Function(WrapFunction(BooleanToString)));
|
||||
prototype->Set("to_string", new Function(WrapFunction(BooleanToString), true));
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
@ -65,11 +65,11 @@ Object::Ptr Dictionary::GetPrototype(void)
|
|||
|
||||
if (!prototype) {
|
||||
prototype = new Dictionary();
|
||||
prototype->Set("len", new Function(WrapFunction(DictionaryLen)));
|
||||
prototype->Set("len", new Function(WrapFunction(DictionaryLen), true));
|
||||
prototype->Set("set", new Function(WrapFunction(DictionarySet)));
|
||||
prototype->Set("remove", new Function(WrapFunction(DictionaryRemove)));
|
||||
prototype->Set("contains", new Function(WrapFunction(DictionaryContains)));
|
||||
prototype->Set("clone", new Function(WrapFunction(DictionaryClone)));
|
||||
prototype->Set("contains", new Function(WrapFunction(DictionaryContains), true));
|
||||
prototype->Set("clone", new Function(WrapFunction(DictionaryClone), true));
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
@ -25,8 +25,8 @@ using namespace icinga;
|
|||
|
||||
REGISTER_PRIMITIVE_TYPE_NOINST(Function, Function::GetPrototype());
|
||||
|
||||
Function::Function(const Callback& function)
|
||||
: m_Callback(function)
|
||||
Function::Function(const Callback& function, bool side_effect_free)
|
||||
: m_Callback(function), m_SideEffectFree(side_effect_free)
|
||||
{ }
|
||||
|
||||
Value Function::Invoke(const std::vector<Value>& arguments)
|
||||
|
@ -34,3 +34,8 @@ Value Function::Invoke(const std::vector<Value>& arguments)
|
|||
return m_Callback(arguments);
|
||||
}
|
||||
|
||||
bool Function::IsSideEffectFree(void) const
|
||||
{
|
||||
return m_SideEffectFree;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,14 +42,16 @@ public:
|
|||
|
||||
typedef boost::function<Value (const std::vector<Value>& arguments)> Callback;
|
||||
|
||||
Function(const Callback& function);
|
||||
Function(const Callback& function, bool side_effect_free = false);
|
||||
|
||||
Value Invoke(const std::vector<Value>& arguments = std::vector<Value>());
|
||||
bool IsSideEffectFree(void) const;
|
||||
|
||||
static Object::Ptr GetPrototype(void);
|
||||
|
||||
private:
|
||||
Callback m_Callback;
|
||||
bool m_SideEffectFree;
|
||||
};
|
||||
|
||||
#define REGISTER_SCRIPTFUNCTION(name, callback) \
|
||||
|
@ -61,6 +63,15 @@ private:
|
|||
INITIALIZE_ONCE(RegisterFunction); \
|
||||
} } }
|
||||
|
||||
#define REGISTER_SAFE_SCRIPTFUNCTION(name, callback) \
|
||||
namespace { namespace UNIQUE_NAME(sf) { namespace sf ## name { \
|
||||
void RegisterFunction(void) { \
|
||||
Function::Ptr sf = new icinga::Function(WrapFunction(callback), true); \
|
||||
ScriptGlobal::Set(#name, sf); \
|
||||
} \
|
||||
INITIALIZE_ONCE(RegisterFunction); \
|
||||
} } }
|
||||
|
||||
}
|
||||
|
||||
#endif /* SCRIPTFUNCTION_H */
|
||||
|
|
|
@ -36,8 +36,8 @@ static void InitializeJsonObj(void)
|
|||
Dictionary::Ptr jsonObj = new Dictionary();
|
||||
|
||||
/* Methods */
|
||||
jsonObj->Set("encode", new Function(WrapFunction(JsonEncodeShim)));
|
||||
jsonObj->Set("decode", new Function(WrapFunction(JsonDecode)));
|
||||
jsonObj->Set("encode", new Function(WrapFunction(JsonEncodeShim), true));
|
||||
jsonObj->Set("decode", new Function(WrapFunction(JsonDecode), true));
|
||||
|
||||
ScriptGlobal::Set("Json", jsonObj);
|
||||
}
|
||||
|
|
|
@ -174,27 +174,27 @@ static void InitializeMathObj(void)
|
|||
mathObj->Set("SQRT2", 1.41421356237309504880);
|
||||
|
||||
/* Methods */
|
||||
mathObj->Set("abs", new Function(WrapFunction(MathAbs)));
|
||||
mathObj->Set("acos", new Function(WrapFunction(MathAcos)));
|
||||
mathObj->Set("asin", new Function(WrapFunction(MathAsin)));
|
||||
mathObj->Set("atan", new Function(WrapFunction(MathAtan)));
|
||||
mathObj->Set("atan2", new Function(WrapFunction(MathAtan2)));
|
||||
mathObj->Set("ceil", new Function(WrapFunction(MathCeil)));
|
||||
mathObj->Set("cos", new Function(WrapFunction(MathCos)));
|
||||
mathObj->Set("exp", new Function(WrapFunction(MathExp)));
|
||||
mathObj->Set("floor", new Function(WrapFunction(MathFloor)));
|
||||
mathObj->Set("log", new Function(WrapFunction(MathLog)));
|
||||
mathObj->Set("max", new Function(WrapFunction(MathMax)));
|
||||
mathObj->Set("min", new Function(WrapFunction(MathMin)));
|
||||
mathObj->Set("pow", new Function(WrapFunction(MathPow)));
|
||||
mathObj->Set("random", new Function(WrapFunction(MathRandom)));
|
||||
mathObj->Set("round", new Function(WrapFunction(MathRound)));
|
||||
mathObj->Set("sin", new Function(WrapFunction(MathSin)));
|
||||
mathObj->Set("sqrt", new Function(WrapFunction(MathSqrt)));
|
||||
mathObj->Set("tan", new Function(WrapFunction(MathTan)));
|
||||
mathObj->Set("isnan", new Function(WrapFunction(MathIsnan)));
|
||||
mathObj->Set("isinf", new Function(WrapFunction(MathIsinf)));
|
||||
mathObj->Set("sign", new Function(WrapFunction(MathSign)));
|
||||
mathObj->Set("abs", new Function(WrapFunction(MathAbs), true));
|
||||
mathObj->Set("acos", new Function(WrapFunction(MathAcos), true));
|
||||
mathObj->Set("asin", new Function(WrapFunction(MathAsin), true));
|
||||
mathObj->Set("atan", new Function(WrapFunction(MathAtan), true));
|
||||
mathObj->Set("atan2", new Function(WrapFunction(MathAtan2), true));
|
||||
mathObj->Set("ceil", new Function(WrapFunction(MathCeil), true));
|
||||
mathObj->Set("cos", new Function(WrapFunction(MathCos), true));
|
||||
mathObj->Set("exp", new Function(WrapFunction(MathExp), true));
|
||||
mathObj->Set("floor", new Function(WrapFunction(MathFloor), true));
|
||||
mathObj->Set("log", new Function(WrapFunction(MathLog), true));
|
||||
mathObj->Set("max", new Function(WrapFunction(MathMax), true));
|
||||
mathObj->Set("min", new Function(WrapFunction(MathMin), true));
|
||||
mathObj->Set("pow", new Function(WrapFunction(MathPow), true));
|
||||
mathObj->Set("random", new Function(WrapFunction(MathRandom), true));
|
||||
mathObj->Set("round", new Function(WrapFunction(MathRound), true));
|
||||
mathObj->Set("sin", new Function(WrapFunction(MathSin), true));
|
||||
mathObj->Set("sqrt", new Function(WrapFunction(MathSqrt), true));
|
||||
mathObj->Set("tan", new Function(WrapFunction(MathTan), true));
|
||||
mathObj->Set("isnan", new Function(WrapFunction(MathIsnan), true));
|
||||
mathObj->Set("isinf", new Function(WrapFunction(MathIsinf), true));
|
||||
mathObj->Set("sign", new Function(WrapFunction(MathSign), true));
|
||||
|
||||
ScriptGlobal::Set("Math", mathObj);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ Object::Ptr Number::GetPrototype(void)
|
|||
|
||||
if (!prototype) {
|
||||
prototype = new Dictionary();
|
||||
prototype->Set("to_string", new Function(WrapFunction(NumberToString)));
|
||||
prototype->Set("to_string", new Function(WrapFunction(NumberToString), true));
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
@ -38,7 +38,7 @@ Object::Ptr Object::GetPrototype(void)
|
|||
|
||||
if (!prototype) {
|
||||
prototype = new Dictionary();
|
||||
prototype->Set("to_string", new Function(WrapFunction(ObjectToString)));
|
||||
prototype->Set("to_string", new Function(WrapFunction(ObjectToString), true));
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
@ -25,13 +25,13 @@ using namespace icinga;
|
|||
boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
|
||||
|
||||
ScriptFrame::ScriptFrame(void)
|
||||
: Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals())
|
||||
: Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals()), Sandboxed(false)
|
||||
{
|
||||
PushFrame(this);
|
||||
}
|
||||
|
||||
ScriptFrame::ScriptFrame(const Value& self)
|
||||
: Locals(new Dictionary()), Self(self)
|
||||
: Locals(new Dictionary()), Self(self), Sandboxed(false)
|
||||
{
|
||||
PushFrame(this);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ struct I2_BASE_API ScriptFrame
|
|||
{
|
||||
Dictionary::Ptr Locals;
|
||||
Value Self;
|
||||
bool Sandboxed;
|
||||
|
||||
ScriptFrame(void);
|
||||
ScriptFrame(const Value& self);
|
||||
|
|
|
@ -33,24 +33,24 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_SCRIPTFUNCTION(regex, &ScriptUtils::Regex);
|
||||
REGISTER_SCRIPTFUNCTION(match, &Utility::Match);
|
||||
REGISTER_SCRIPTFUNCTION(len, &ScriptUtils::Len);
|
||||
REGISTER_SCRIPTFUNCTION(union, &ScriptUtils::Union);
|
||||
REGISTER_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(regex, &ScriptUtils::Regex);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(match, &Utility::Match);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(len, &ScriptUtils::Len);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(union, &ScriptUtils::Union);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
|
||||
REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
|
||||
REGISTER_SCRIPTFUNCTION(range, &ScriptUtils::Range);
|
||||
REGISTER_SCRIPTFUNCTION(exit, &Application::Exit);
|
||||
REGISTER_SCRIPTFUNCTION(typeof, &ScriptUtils::TypeOf);
|
||||
REGISTER_SCRIPTFUNCTION(keys, &ScriptUtils::Keys);
|
||||
REGISTER_SCRIPTFUNCTION(random, &Utility::Random);
|
||||
REGISTER_SCRIPTFUNCTION(get_object, &ScriptUtils::GetObject);
|
||||
REGISTER_SCRIPTFUNCTION(get_objects, &ScriptUtils::GetObjects);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(typeof, &ScriptUtils::TypeOf);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(keys, &ScriptUtils::Keys);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(random, &Utility::Random);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(get_object, &ScriptUtils::GetObject);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(get_objects, &ScriptUtils::GetObjects);
|
||||
REGISTER_SCRIPTFUNCTION(assert, &ScriptUtils::Assert);
|
||||
REGISTER_SCRIPTFUNCTION(string, &ScriptUtils::CastString);
|
||||
REGISTER_SCRIPTFUNCTION(number, &ScriptUtils::CastNumber);
|
||||
REGISTER_SCRIPTFUNCTION(bool, &ScriptUtils::CastBool);
|
||||
REGISTER_SCRIPTFUNCTION(get_time, &Utility::GetTime);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(string, &ScriptUtils::CastString);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(number, &ScriptUtils::CastNumber);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(bool, &ScriptUtils::CastBool);
|
||||
REGISTER_SAFE_SCRIPTFUNCTION(get_time, &Utility::GetTime);
|
||||
|
||||
String ScriptUtils::CastString(const Value& value)
|
||||
{
|
||||
|
|
|
@ -133,15 +133,15 @@ Object::Ptr String::GetPrototype(void)
|
|||
|
||||
if (!prototype) {
|
||||
prototype = new Dictionary();
|
||||
prototype->Set("len", new Function(WrapFunction(StringLen)));
|
||||
prototype->Set("to_string", new Function(WrapFunction(StringToString)));
|
||||
prototype->Set("substr", new Function(WrapFunction(StringSubstr)));
|
||||
prototype->Set("upper", new Function(WrapFunction(StringUpper)));
|
||||
prototype->Set("lower", new Function(WrapFunction(StringLower)));
|
||||
prototype->Set("split", new Function(WrapFunction(StringSplit)));
|
||||
prototype->Set("find", new Function(WrapFunction(StringFind)));
|
||||
prototype->Set("contains", new Function(WrapFunction(StringContains)));
|
||||
prototype->Set("replace", new Function(WrapFunction(StringReplace)));
|
||||
prototype->Set("len", new Function(WrapFunction(StringLen), true));
|
||||
prototype->Set("to_string", new Function(WrapFunction(StringToString), true));
|
||||
prototype->Set("substr", new Function(WrapFunction(StringSubstr), true));
|
||||
prototype->Set("upper", new Function(WrapFunction(StringUpper), true));
|
||||
prototype->Set("lower", new Function(WrapFunction(StringLower), true));
|
||||
prototype->Set("split", new Function(WrapFunction(StringSplit), true));
|
||||
prototype->Set("find", new Function(WrapFunction(StringFind), true));
|
||||
prototype->Set("contains", new Function(WrapFunction(StringContains), true));
|
||||
prototype->Set("replace", new Function(WrapFunction(StringReplace), true));
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
@ -59,6 +59,7 @@ void ConsoleCommand::InitParameters(boost::program_options::options_description&
|
|||
{
|
||||
visibleDesc.add_options()
|
||||
("connect,c", po::value<std::string>(), "connect to an Icinga 2 instance")
|
||||
("sandbox", "enable sandbox mode")
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -194,6 +195,15 @@ int ConsoleCommand::Run(const po::variables_map& vm, const std::vector<std::stri
|
|||
session = Utility::NewUniqueID();
|
||||
}
|
||||
|
||||
if (vm.count("sandbox")) {
|
||||
if (vm.count("connect")) {
|
||||
Log(LogCritical, "ConsoleCommand", "Sandbox mode cannot be used together with --connect.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
l_ScriptFrame.Sandboxed = true;
|
||||
}
|
||||
|
||||
std::cout << "Icinga (version: " << Application::GetVersion() << ")\n";
|
||||
|
||||
while (std::cin.good()) {
|
||||
|
|
|
@ -414,6 +414,9 @@ ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHin
|
|||
|
||||
Function::Ptr func = vfunc;
|
||||
|
||||
if (!func->IsSideEffectFree() && frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Function is not marked as safe for sandbox mode.", m_DebugInfo));
|
||||
|
||||
std::vector<Value> arguments;
|
||||
BOOST_FOREACH(Expression *arg, m_Args) {
|
||||
ExpressionResult argres = arg->Evaluate(frame);
|
||||
|
@ -483,6 +486,9 @@ ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
|
|||
|
||||
ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Assignments are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
DebugHint *psdhint = dhint;
|
||||
|
||||
Value parent;
|
||||
|
@ -565,6 +571,9 @@ ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint
|
|||
|
||||
ExpressionResult WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("While loops are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
for (;;) {
|
||||
ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
|
||||
CHECK_RESULT(condition);
|
||||
|
@ -618,6 +627,9 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
|
|||
if (dhint)
|
||||
psdhint = *dhint;
|
||||
|
||||
if (frame.Sandboxed)
|
||||
init_dict = false;
|
||||
|
||||
if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
|
||||
if (init_dict && VMOps::GetField(vparent, vindex, m_Operand1->GetDebugInfo()).IsEmpty())
|
||||
VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
|
||||
|
@ -687,6 +699,9 @@ void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec)
|
|||
|
||||
ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
String type = VMOps::GetField(frame.Self, "type", m_DebugInfo);
|
||||
ExpressionResult nameres = m_Name->Evaluate(frame);
|
||||
CHECK_RESULT(nameres);
|
||||
|
@ -713,6 +728,9 @@ ExpressionResult FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
|
|||
|
||||
ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
ExpressionResult nameres = m_Name->Evaluate(frame);
|
||||
CHECK_RESULT(nameres);
|
||||
|
||||
|
@ -722,6 +740,9 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin
|
|||
|
||||
ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
String name;
|
||||
|
||||
if (m_Name) {
|
||||
|
@ -737,6 +758,9 @@ ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhi
|
|||
|
||||
ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
if (frame.Sandboxed)
|
||||
BOOST_THROW_EXCEPTION(ScriptError("For loops are not allowed in sandbox mode.", m_DebugInfo));
|
||||
|
||||
ExpressionResult valueres = m_Value->Evaluate(frame, dhint);
|
||||
CHECK_RESULT(valueres);
|
||||
|
||||
|
|
Loading…
Reference in New Issue