#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             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-
# tails. 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.

# Example output from agent:
# <<<sshd_config>>>
# Port 22
# Port 12345
# Protocol 2,1
# ChallengeResponseAuthentication no
# UsePAM yes
# X11Forwarding yes
# PrintMotd no
# AcceptEnv LANG LC_*
# Subsystem sftp /usr/lib/openssh/sftp-server


def parse_sshd_config(info):
    identity = lambda x: x
    relevant_options = {
        #option                             parse function
        "Protocol":                         lambda x: ",".join(sorted(x.split(","))),
        # Port can be defined multiple times in sshd_config.
        # Therefore we use a list of ints.
        "Port":                             lambda x: [int(x)],
        "PermitRootLogin":                  identity,
        "PasswordAuthentication":           identity,
        "PermitEmptyPasswords":             identity,
        "ChallengeResponseAuthentication":  identity,
        "X11Forwarding":                    identity,
        "UsePAM":                           identity,
        "Ciphers":                          lambda x: sorted(x.split(",")),
    }

    parsed = {}
    for line in info:
        if len(line) < 2:
            continue

        key, val = line[0], " ".join(line[1:])
        if key not in relevant_options:
            continue

        parse_func = relevant_options[key]
        val = parse_func(val)

        if not key in parsed:
            parsed[key] = val
        else:
            parsed[key] += val

    return parsed


def inventory_sshd_config(parsed):
    return [(None, {})]


def check_sshd_config(_no_item, params, parsed):
    # type_ is needed because info contains unicode and params str
    convert = lambda x, type_: (x if isinstance(x, type_)
                                else ", ".join(map(type_, x)))

    for option, val in parsed.iteritems():
        state = 0
        infotext = "%s: %s" % (option, convert(val, unicode))

        expected = params.get(option)
        if expected and expected != val:
            state = 2
            infotext += " (expected %s)" % convert(expected, str)

        yield state, infotext

    for option in params:
        if not option in parsed:
            yield 2, "%s: not present in sshd_config" % option


check_info["sshd_config"] = {
    "parse_function":          parse_sshd_config,
    "inventory_function":      inventory_sshd_config,
    "check_function":          check_sshd_config,
    "service_description":     "SSH daemon configuration",
    "group":                   "sshd_config",
}

