#!/bin/bash
# vim: et sts=4 sw=4

# SPDX-License-Identifier: GPL-3.0-only
# Copyright 2021 Offensive Security

# References: smb.conf(5), section FILE FORMAT
# 
# The parts that matter for this script:
# * Section and parameter names are not case sensitive.
# * Only the first equals sign in a parameter is significant. Whitespace before
#   or after the first equals sign is discarded. Leading, trailing and internal
#   whitespace in section and parameter names is irrelevant. Leading and
#   trailing whitespace in a parameter value is discarded. Internal whitespace
#   within a parameter value is retained verbatim. 

set -e
set -u

SAMBA_CONFIG=  # $1
CMD=           # $2

exit_with_usage() {
    echo >&2 "Usage: $(basename $0) SAMBA_CONFIG_FILE CMD [ARGS]"
    echo >&2 "CMD can be: get, set compat/default"
    exit 1
}

assert_file_exists() {
    if ! test -e "$1"; then
        echo >&2 "File '$1' does not exist"
        exit 1
    fi
}

assert_config_file_valid() {
    if ! command -v testparm >/dev/null; then
        # Assume file is valid then. testparm is not necessarily
        # present when running unit tests.
        return
    fi

    # Workaround https://bugs.debian.org/1022826
    local conffile=$SAMBA_CONFIG
    if [ "$SAMBA_CONFIG" = "/etc/samba/smb.conf" ]; then
        conffile=
    fi

    if ! testparm $conffile --suppress-prompt >/dev/null 2>&1; then
        # do it again to output error message
        testparm $conffile --suppress-prompt
        exit 1
    fi
}

do_get() {

    # Get the value for the setting 'client min protocol'. Returns 'default'
    # if the setting is unset, otherwise returns the setting as is.

    local val=

    # If the setting is not defined, it means its value is set to default.
    if ! grep -Eiq "^ *client +min +protocol *=" $SAMBA_CONFIG; then
        echo "default"
        return
    fi

    # Otherwise, let's get the value then. If the value is set
    # more than once, the last line wins. This is not explicitly
    # documented, but that's how testparm handles it.
    val=$(cat $SAMBA_CONFIG | sed -En "s/^ *client +min +protocol *= *//Ip" | sed "s/ *$//")
    val=$(echo "$val" | tail -1)

    echo "$val"

    # The following line is useful to get the exact value of the parameter,
    # regardless of the fact that it's defined in the config or not. However,
    # turns out we don't actually need that...
    #testparm $SAMBA_CONFIG --suppress-prompt \
    #    --parameter-name 'client min protocol' 2>/dev/null
}

do_set() {
   
    # Set the value for the setting 'client min protocol'. 'default' means to
    # comment out the setting, otherwise the value is written as is.

    local val=$1

    # Default value means to comment out the line with a leading ';'.
    # Read the beginning of the file etc/samba/smb.conf for the
    # difference between '#' and ';'.
    if [ "$val" = "default" ]; then
        sed -Ei "/^ *client +min +protocol *=/Is/^/;/" $SAMBA_CONFIG
        return
    fi

    # If the line exists and is commented out, uncomment it.
    sed -Ei "s/^([#;]+)( *client +min +protocol *= *)/\2/I" $SAMBA_CONFIG

    # If the line exists, set the value, otherwise add the line with the right value.
    if grep -Eiq "^ *client +min +protocol *=" $SAMBA_CONFIG; then
        sed -Ei "s/^( *client +min +protocol *= *).*/\1${val}/I" $SAMBA_CONFIG
    else
        sed -Ei "/^ *\[ *global *\] *$/a \\\n# Added by kali-tweaks\n   client min protocol = ${val}" $SAMBA_CONFIG
    fi
}


## main


[ $# -ge 2 ] || exit_with_usage

SAMBA_CONFIG=$1 ; shift
CMD=$1          ; shift

assert_file_exists $SAMBA_CONFIG
assert_config_file_valid

case "$CMD" in
    (get)
        [ $# -eq 0 ] || exit_with_usage
        do_get
        ;;
    (set)
        [ $# -eq 1 ] || exit_with_usage
        do_set "$1"
        ;;
    (*)
        exit_with_usage
        ;;
esac
