source: nscp/modules/CheckExternalScripts/CheckExternalScripts.cpp @ 67c6d04

0.4.00.4.10.4.2
Last change on this file since 67c6d04 was 67c6d04, checked in by Michael Medin <michael@…>, 13 months ago
  • Property mode set to 100644
File size: 11.1 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#include "stdafx.h"
22#include "CheckExternalScripts.h"
23#include <time.h>
24#include <string>
25
26#include <strEx.h>
27#include <file_helpers.hpp>
28
29#include <boost/regex.hpp>
30#include <boost/filesystem.hpp>
31
32#include <settings/client/settings_client.hpp>
33#include <nscapi/functions.hpp>
34#include <nscapi/nscapi_core_helper.hpp>
35
36#include <config.h>
37
38namespace sh = nscapi::settings_helper;
39
40CheckExternalScripts::CheckExternalScripts() {}
41CheckExternalScripts::~CheckExternalScripts() {}
42
43void CheckExternalScripts::addAllScriptsFrom(std::wstring str_path) {
44        boost::filesystem::wpath path = str_path;
45        if (path.has_relative_path())
46                path = get_core()->getBasePath() / path;
47        file_helpers::patterns::pattern_type split_path = file_helpers::patterns::split_pattern(path);
48        if (!boost::filesystem::is_directory(split_path.first))
49                NSC_LOG_ERROR_STD(_T("Path was not found: ") + split_path.first.string());
50
51        boost::wregex pattern(split_path.second);
52        boost::filesystem::wdirectory_iterator end_itr; // default construction yields past-the-end
53        for ( boost::filesystem::wdirectory_iterator itr( split_path.first ); itr != end_itr; ++itr ) {
54                if ( !is_directory(itr->status()) ) {
55                        std::wstring name = itr->path().leaf();
56                        if (regex_match(name, pattern))
57                                add_command(name.c_str(), (split_path.first / name).string());
58                }
59        }
60}
61
62
63/**
64 * Load (initiate) module.
65 * Start the background collector thread and let it run until unloadModule() is called.
66 * @return true
67 */
68bool CheckExternalScripts::loadModule() {
69        return false;
70}
71
72
73
74bool CheckExternalScripts::loadModuleEx(std::wstring alias, NSCAPI::moduleLoadMode mode) {
75        try {
76
77                sh::settings_registry settings(get_settings_proxy());
78                settings.set_alias(alias, _T("external scripts"));
79
80                commands_path = settings.alias().get_settings_path(_T("scripts"));
81                aliases_path = settings.alias().get_settings_path(_T("alias"));
82                std::wstring wrappings_path = settings.alias().get_settings_path(_T("wrappings"));
83
84                settings.alias().add_path_to_settings()
85
86                        (_T("wrappings"), sh::wstring_map_path(&wrappings_)
87                        , _T("EXTERNAL SCRIPT WRAPPINGS SECTION"), _T("A list of templates for wrapped scripts"))
88
89                        ;
90
91                settings.register_all();
92                settings.notify();
93                settings.clear();
94
95                if (wrappings_.empty()) {
96                        NSC_DEBUG_MSG(_T("No wrappings found (adding default: vbs, ps1 and bat)"));
97                        wrappings_[_T("vbs")] = _T("cscript.exe //T:30 //NoLogo scripts\\\\lib\\\\wrapper.vbs %SCRIPT% %ARGS%");
98                        wrappings_[_T("ps1")] = _T("cmd /c echo scripts\\\\%SCRIPT% %ARGS%; exit($lastexitcode) | powershell.exe -command -");
99                        wrappings_[_T("bat")] = _T("scripts\\\\%SCRIPT% %ARGS%");
100                        get_core()->settings_register_key(wrappings_path, _T("vbs"), NSCAPI::key_string, _T("VISUAL BASIC WRAPPING"), _T(""), wrappings_[_T("vbs")], false);
101                        get_core()->settings_register_key(wrappings_path, _T("ps1"), NSCAPI::key_string, _T("POWERSHELL WRAPPING"), _T(""), wrappings_[_T("ps1")], false);
102                        get_core()->settings_register_key(wrappings_path, _T("bat"), NSCAPI::key_string, _T("BATCH FILE WRAPPING"), _T(""), wrappings_[_T("bat")], false);
103                }
104
105                settings.alias().add_path_to_settings()
106                        (_T("EXTERNAL SCRIPT SECTION"), _T("Section for external scripts configuration options (CheckExternalScripts)."))
107
108                        (_T("scripts"), sh::fun_values_path(boost::bind(&CheckExternalScripts::add_command, this, _1, _2)),
109                        _T("EXTERNAL SCRIPT SCRIPT SECTION"), _T("A list of scripts available to run from the CheckExternalScripts module. Syntax is: <command>=<script> <arguments>"))
110
111                        (_T("alias"), sh::fun_values_path(boost::bind(&CheckExternalScripts::add_alias, this, _1, _2)),
112                        _T("EXTERNAL SCRIPT ALIAS SECTION"), _T("A list of aliases available. An alias is an internal command that has been \"wrapped\" (to add arguments). Be careful so you don't create loops (ie check_loop=check_a, check_a=check_loop)"))
113
114                        (_T("wrapped scripts"), sh::fun_values_path(boost::bind(&CheckExternalScripts::add_wrapping, this, _1, _2)),
115                        _T("EXTERNAL SCRIPT WRAPPED SCRIPTS SECTION"), _T("A list of wrappped scripts (ie. using the template mechanism)"))
116
117                        ;
118
119                settings.alias().add_key_to_settings()
120                        (_T("timeout"), sh::uint_key(&timeout, 60),
121                        _T("COMMAND TIMEOUT"), _T("The maximum time in seconds that a command can execute. (if more then this execution will be aborted). NOTICE this only affects external commands not internal ones."))
122
123                        (_T("allow arguments"), sh::bool_key(&allowArgs_, false),
124                        _T("COMMAND ARGUMENT PROCESSING"), _T("This option determines whether or not the we will allow clients to specify arguments to commands that are executed."))
125
126                        (_T("allow nasty characters"), sh::bool_key(&allowNasty_, false),
127                        _T("COMMAND ALLOW NASTY META CHARS"), _T("This option determines whether or not the we will allow clients to specify nasty (as in |`&><'\"\\[]{}) characters in arguments."))
128
129                        (_T("script path"), sh::wstring_key(&scriptDirectory_),
130                        _T("SCRIPT DIRECTORY"), _T("Load all scripts in a directory and use them as commands. Probably dangerous but useful if you have loads of scripts :)"))
131                        ;
132
133                settings.register_all();
134                settings.notify();
135
136
137                if (!scriptDirectory_.empty()) {
138                        addAllScriptsFrom(scriptDirectory_);
139                }
140                root_ = get_core()->getBasePath();
141
142                BOOST_FOREACH(const commands::command_handler::object_list_type::value_type &o, commands_.object_list) {
143                        NSC_DEBUG_MSG(_T("Registring command: ") + o.second.to_wstring());
144                        register_command(o.second.alias, _T("Alias for: ") + o.second.alias);
145                }
146                BOOST_FOREACH(const commands::command_handler::object_list_type::value_type &o, aliases_.object_list) {
147                        NSC_DEBUG_MSG(_T("Registring alias: ") + o.second.to_wstring());
148                        register_command(o.second.alias, _T("Alias for: ") + o.second.alias);
149                }
150
151
152//      } catch (nrpe::server::nrpe_exception &e) {
153//              NSC_LOG_ERROR_STD(_T("Exception caught: ") + e.what());
154//              return false;
155        } catch (...) {
156                NSC_LOG_ERROR_STD(_T("Exception caught: <UNKNOWN EXCEPTION>"));
157                return false;
158        }
159        return true;
160}
161bool CheckExternalScripts::unloadModule() {
162        return true;
163}
164
165void CheckExternalScripts::add_command(std::wstring key, std::wstring arg) {
166        try {
167                commands_.add(get_settings_proxy(), commands_path, key, arg, key == _T("default"));
168        } catch (const std::exception &e) {
169                NSC_LOG_ERROR_STD(_T("Failed to add command: ") + key + _T(", ") + utf8::to_unicode(e.what()));
170        } catch (...) {
171                NSC_LOG_ERROR_STD(_T("Failed to add command: ") + key);
172        }
173}
174void CheckExternalScripts::add_alias(std::wstring key, std::wstring arg) {
175        try {
176                aliases_.add(get_settings_proxy(), aliases_path, key, arg, key == _T("default"));
177        } catch (const std::exception &e) {
178                NSC_LOG_ERROR_STD(_T("Failed to add alias: ") + key + _T(", ") + utf8::to_unicode(e.what()));
179        } catch (...) {
180                NSC_LOG_ERROR_STD(_T("Failed to add alias: ") + key);
181        }
182}
183
184
185bool CheckExternalScripts::hasCommandHandler() {
186        return true;
187}
188bool CheckExternalScripts::hasMessageHandler() {
189        return false;
190}
191
192NSCAPI::nagiosReturn CheckExternalScripts::handleRAWCommand(const wchar_t* char_command, const std::string &request, std::string &response) {
193        nscapi::functions::decoded_simple_command_data data = nscapi::functions::parse_simple_query_request(char_command, request);
194
195        commands::optional_command_object cmd = commands_.find_object(data.command);
196        bool isAlias = !cmd;
197        if (!cmd)
198                cmd = aliases_.find_object(data.command);
199        if (!cmd)
200                return NSCAPI::returnIgnored;
201
202        const commands::command_object cd = *cmd;
203        std::list<std::wstring> args = cd.arguments;
204        bool first = true;
205        if (isAlias || allowArgs_) {
206                BOOST_FOREACH(std::wstring &arg, args) {
207                        int i=1;
208                        BOOST_FOREACH(std::wstring str, data.args) {
209                                if (first && !isAlias && !allowNasty_) {
210                                        if (str.find_first_of(NASTY_METACHARS_W) != std::wstring::npos) {
211                                                return nscapi::functions::create_simple_query_response_unknown(data.command, _T("Request contained illegal characters!"), _T(""), response);
212                                        }
213                                }
214                                strEx::replace(arg, _T("$ARG") + strEx::itos(i++) + _T("$"), str);
215                        }
216                }
217        } else if (!allowArgs_ && data.args.size() > 0) {
218                NSC_LOG_ERROR_STD(_T("Arguments not allowed in CheckExternalScripts set /settings/external scripts/allow arguments=true"))
219        }
220
221
222        std::wstring xargs;
223        BOOST_FOREACH(std::wstring s, args) {
224                if (!xargs.empty())
225                        xargs += _T(" ");
226                xargs += s;
227        }
228
229        NSC_LOG_MESSAGE(_T("Arguments: ") + xargs);
230
231
232        if (isAlias) {
233                std::wstring message;
234                try {
235                        return nscapi::core_helper::simple_query(cd.command, args, response);
236                } catch (boost::escaped_list_error &e) {
237                        NSC_LOG_MESSAGE(_T("Failed to parse alias expression: ") + strEx::string_to_wstring(e.what()));
238                        NSC_LOG_MESSAGE(_T("We will now try parsing the old syntax instead..."));
239                        return nscapi::core_helper::simple_query(cd.command, args, response);
240                }
241        } else {
242                std::wstring message, perf;
243                process::exec_arguments args(root_, cd.command + _T(" ") + xargs, timeout);
244                if (!cd.user.empty()) {
245                        args.user = cd.user;
246                        args.domain = cd.domain;
247                        args.password = cd.password;
248                }
249                int result = process::executeProcess(args, message, perf);
250                if (!nscapi::plugin_helper::isNagiosReturnCode(result)) {
251                        nscapi::functions::create_simple_query_response_unknown(data.command, _T("The command (") + args.command + _T(") returned an invalid return code: ") + strEx::itos(result), _T(""), response);
252                        return NSCAPI::returnUNKNOWN;
253                }
254                nscapi::functions::create_simple_query_response(data.command, nscapi::plugin_helper::int2nagios(result), message, perf, response);
255                return result;
256        }
257}
258NSC_WRAP_DLL();
259NSC_WRAPPERS_MAIN_DEF(CheckExternalScripts);
260NSC_WRAPPERS_IGNORE_MSG_DEF();
261NSC_WRAPPERS_HANDLE_CMD_DEF();
262
Note: See TracBrowser for help on using the repository browser.