This file is indexed.

/usr/share/check_mk/checks/logwatch is in check-mk-server 1.1.12-1ubuntu1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2010             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk 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 in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# ails.  You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.


# Configuration variables in main.mk needed during the actual check
logwatch_dir = var_dir + '/logwatch'
logwatch_patterns = { }
logwatch_max_filesize = 500000 # do not save more than 500k of message (configurable)

# Variables embedded in precompiled checks
check_config_variables += [ "logwatch_dir", "logwatch_max_filesize" ]

def inventory_logwatch(info):
    inventory = []
    for l in info:
        line = " ".join(l)
        if len(line) > 6 and line[0:3] == "[[[" and line[-3:] == "]]]" and ':' not in line:
            inventory.append((line[3:-3], "", '""'))
    return inventory

#logwatch_patterns = {
#    'System': [
#    ( 'W', 'sshd' ),
#    ( ['host1', 'host2'], 'C', 'ssh' ), # only applies to certain hosts
#    ( ['lnx', 'dmz'], ALL_HOSTS, 'C', 'ssh' ), # only applies to host having certain tags

#    ( 'I', '0' )
#    ],
#    'Application': [
#    ( 'W', 'crash.exe' ),
#    ( 'E', 'ssh' )
#    ]
#    }

# Extracts only pattern relevant for current host and item.
# Constructs simple list of pairs: [ ('W', 'crash.exe'), ('C', 'sshd.*test') ]
def logwatch_precompile(hostname, item, params):
    patterns = logwatch_patterns.get(item)
    params = []
    if patterns:
        for entry in patterns:
            hostlist = None
            tags = []

            pattern = entry[-1]
            level = entry[-2]

            if len(entry) >= 3:    # found optional host list
                hostlist = entry[-3]
            if len(entry) >= 4:    # found optional host tags
                tags = entry[-4]

            if hostlist and not \
                   (hosttags_match_taglist(tags_of_host(hostname), tags) and \
                    in_extraconf_hostlist(hostlist, hostname)):
                continue

            params.append((level, pattern))
    return params


def logwatch_reclassify(patterns, text):
    for level, pattern in patterns:
        reg = compiled_regexes.get(pattern)
        if not reg:
            reg = re.compile(pattern)
            compiled_regexes[pattern] = reg
        if reg.search(text):
            return level
    return None

# In case of a precompiled check, params contains the precompiled
# logwatch_patterns for the logfile we deal with. If using check_mk
# without precompiled checks, the params must be None an will be
# ignored.
def check_logwatch(item, params, info):
    found = False
    loglines = []
    for l in info:
        line = " ".join(l)
        if line == "[[[%s]]]" % item:
            found = True
        elif len(line) > 6 and line[0:3] == "[[[" and line[-3:] == "]]]":
            if found:
                break
            found = False
        elif found:
            loglines.append(line)

    # Create directories, if neccessary
    try:
        logdir = logwatch_dir + "/" + g_hostname
        if not os.path.exists(logwatch_dir):
            os.mkdir(logwatch_dir)
        if not os.path.exists(logdir):
            os.mkdir(logdir)
            if www_group != None:
                try:
                    if i_am_root():
                        import pwd
                        to_user = pwd.getpwnam(nagios_user)[2]
                    else:
                        to_user = -1 # keep user unchanged
                    os.chown(logdir, to_user, www_group)
                    os.chmod(logdir, 0775)
                except Exception, e:
                    os.rmdir(logdir)
                    raise MKGeneralException(("User %s cannot chown directory to group id %d: %s. Please make sure "+
                                             "that %s is a member of that group.") %
                                             (username(), www_group, e, username()))

    except MKGeneralException:
        raise
    except Exception, e:
        raise MKGeneralException("User %s cannot create logwatch directory: %s" % \
                                 (username(), e) )

    logfile = logdir + "/" + item.replace("/", "\\")

    # Logfile (=item) section not found and no local file found. This usually
    # means, that the corresponding logfile also vanished on the target host.
    if found == False and not os.path.exists(logfile):
        return (3, "UNKNOWN - log not present anymore")

    # if logfile has reached maximum size, abort with critical state
    if os.path.exists(logfile) and os.path.getsize(logfile) > logwatch_max_filesize:
        return (2, "CRIT - unacknowledged messages have exceeded max size (%d Bytes)" % logwatch_max_filesize)

    if len(loglines) > 0 and loglines[0] in [ 'OK', 'WARNING', 'CRITICAL' ]:
        # --------------------------------------------------------------------
        # ALTE VERSION DES AGENTEN:
        # 23.10.2008 fiebig k-h  extend the function to handle nagios state yellow
        if loglines[0] != "OK" :
            logarch = file(logfile, "a+")
            logarch.write(time.strftime("<<<%Y-%m-%d %H:%M:%S>>>\n"))
            logarch.write("\n".join(loglines) + "\n")

        if not os.path.exists(logfile) and loglines[0] == "OK":
            return (0, "OK - no old or new error messages")
        elif  os.path.exists(logfile) and loglines[0] == "OK":
            if str(file(logfile).readlines()).count("CRITICAL") > 0 :
                return (2, "CRIT - error messages present!")
            else:
                return (1, "WARN - error messages present!")
        elif  os.path.exists(logfile) and loglines[0] != "OK":
            if str(file(logfile).readlines()).count("CRITICAL") > 0 :
                return (2, "CRIT - error messages present!")
            else:
                return (1, "WARN - error messages present!")
        elif loglines[0] == "WARNING" :
            return (1, "WARN - error messages present!")
        elif loglines[0] == "CRITICAL" :
            return (2, "CRIT - error messages present!")
        # ENDE ALTE VERSION DES AGENTEN
        # --------------------------------------------------------------------
    else:
        had_old_messages = os.path.exists(logfile)
        if params:
            patterns = params # patterns already precompiled
        else:
            patterns = logwatch_precompile(g_hostname, item, None)

        if len(loglines) > 0:
            worst = 0
            newloglines = []
            for line in loglines:
                parts = line.split(None, 1)
                level = parts[0]
                if len(parts) > 1:
                    text = parts[1]
                else:
                    text = ""
                if patterns and level != '.': # do never reclassify informational context messages
                    newlevel = logwatch_reclassify(patterns, text)
                    if newlevel != None:
                        level = newlevel

                if   level == 'W': worst = max(worst, 1)
                elif level == 'C': worst = max(worst, 2)
                newloglines.append(level + ' ' + text)

            if worst == 1:
                state = "WARN"
            elif worst != 0:
                state = "CRIT"
            else:
                state = "OK"

            # Append new logfile lines to archive file. If state is "OK, do not
            # write anything
            if worst > 0:
                try:
                    logarch = file(logfile, "a+")
                    logarch.write(time.strftime("<<<%Y-%m-%d %H:%M:%S " + state + ">>>\n"))
                    logarch.write("\n".join(newloglines) + "\n")
                except Exception, e:
                    raise MKGeneralException("User %s cannot create logfile: %s" % \
                                             (username(), e))
            else:
                logfiles = [] # appearently all logfiles reclassified to "I"

        # Determine current state by scanning logarch for status
        if not had_old_messages and len(loglines) == 0:
            return (0, "OK - no old or new error messages")
        elif not had_old_messages and len(loglines) > 0:
            return (worst, state + " - %d new messages!" % len(newloglines))
        else:
            # had old messages. Scan old archive log messages for state
            logarch = file(logfile)
            state = "WARN"
            worst = 1
            for line in logarch:
                if line.endswith("CRIT>>>\n"):
                    state = "CRIT"
                    worst = 2
                    break
            if len(loglines) > 0:
                return (worst, state + " - some old and %d new messages present!" % len(newloglines))
            else:
                return (worst, state + " - error messages present!")


check_info['logwatch'] = (
    check_logwatch,
    "LOG %s",
    0,
    inventory_logwatch)

precompile_params['logwatch'] = logwatch_precompile