regexp: ^^ \s* Port \s+ (\d+) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

port = None
for c in captures():
    port = c[0]
if port:
    if 1 <= int(port) <= 65535:
        print(f"assert: 1 port is valid ({port})")
    else:
        print(f"assert: 0 port out of range ({port})")
else:
    print("assert: 0 port not found")
CODE

regexp: ^^ \s* Protocol \s+ (\d) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

proto = None
for c in captures():
    proto = c[0]
if proto:
    if proto == "2":
        print("assert: 1 Protocol version is 2")
    else:
        print(f"assert: 0 Protocol version is {proto} (expected 2)")
else:
    print("assert: 0 Protocol not found")
CODE

regexp: ^^ \s* ListenAddress \s+ ( \S+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

addr = None
for c in captures():
    addr = c[0]
if addr:
    print(f"assert: 1 ListenAddress found ({addr})")
else:
    print("assert: 0 ListenAddress not found")
CODE

regexp: :i ^^ \s* PermitRootLogin \s+ ( yes | no | prohibit\-password | forced\-commands\-only ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if val.lower() in ("no", "prohibit-password"):
        print(f"assert: 1 PermitRootLogin securely set to {val}")
    else:
        print(f"assert: 0 PermitRootLogin is {val} (should be no or prohibit-password)")
else:
    print("assert: 0 PermitRootLogin not set")
CODE

regexp: :i ^^ \s* PasswordAuthentication \s+ ( yes | no ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if val.lower() == "no":
        print("assert: 1 PasswordAuthentication disabled")
    else:
        print(f"assert: 0 PasswordAuthentication is {val}")
else:
    print("assert: 0 PasswordAuthentication not set")
CODE

regexp: :i ^^ \s* PubkeyAuthentication \s+ ( yes | no ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if val.lower() == "yes":
        print("assert: 1 PubkeyAuthentication enabled")
    else:
        print(f"assert: 0 PubkeyAuthentication is {val}")
else:
    print("assert: 0 PubkeyAuthentication not set")
CODE

regexp: ^^ \s* MaxAuthTries \s+ (\d+) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if int(val) <= 6:
        print(f"assert: 1 MaxAuthTries <= 6 ({val})")
    else:
        print(f"assert: 0 MaxAuthTries is {val} (should be <= 6)")
else:
    print("assert: 0 MaxAuthTries not found")
CODE

regexp: ^^ \s* MaxSessions \s+ (\d+) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if int(val) <= 10:
        print(f"assert: 1 MaxSessions <= 10 ({val})")
    else:
        print(f"assert: 0 MaxSessions is {val} (should be <= 10)")
else:
    print("assert: 0 MaxSessions not found")
CODE

regexp: ^^ \s* LoginGraceTime \s+ (\d+) \s* <[smhd]> \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
unit = None
for c in captures():
    val = c[0]
    if len(c) > 1:
        unit = c[1]
if val:
    print(f"assert: 1 LoginGraceTime set to {val}{unit if unit else ''}")
else:
    print("assert: 0 LoginGraceTime not found")
CODE

regexp: :i ^^ \s* PermitEmptyPasswords \s+ ( yes | no ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if val.lower() == "no":
        print("assert: 1 empty passwords forbidden")
    else:
        print(f"assert: 0 PermitEmptyPasswords is {val}")
else:
    print("assert: 0 PermitEmptyPasswords not set")
CODE

regexp: :i ^^ \s* X11Forwarding \s+ ( yes | no ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if val.lower() == "no":
        print("assert: 1 X11Forwarding disabled")
    else:
        print(f"assert: 0 X11Forwarding is {val}")
else:
    print("assert: 0 X11Forwarding not set")
CODE

regexp: ^^ \s* ClientAliveInterval \s+ (\d+) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if int(val) > 0:
        print(f"assert: 1 ClientAliveInterval {val}")
    else:
        print(f"assert: 0 ClientAliveInterval is 0 (should be >0)")
else:
    print("assert: 0 ClientAliveInterval not set")
CODE

regexp: ^^ \s* ClientAliveCountMax \s+ (\d+) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if int(val) <= 3:
        print(f"assert: 1 ClientAliveCountMax {val} (<=3)")
    else:
        print(f"assert: 0 ClientAliveCountMax {val} (>3)")
else:
    print("assert: 0 ClientAliveCountMax not set")
CODE

regexp: :i ^^ \s* UseDNS \s+ ( yes | no ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

val = None
for c in captures():
    val = c[0]
if val:
    if val.lower() == "no":
        print("assert: 1 UseDNS disabled")
    else:
        print(f"assert: 0 UseDNS is {val}")
else:
    print("assert: 0 UseDNS not set")
CODE

regexp: :i ^^ \s* Ciphers \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

ciphers = None
for c in captures():
    ciphers = c[0]
if ciphers:
    if "aes256" in ciphers.lower():
        print(f"assert: 1 strong cipher present")
    else:
        print(f"assert: 0 no strong cipher found")
else:
    print("assert: 0 Ciphers not configured")
CODE

regexp: :i ^^ \s* MACs \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

macs = None
for c in captures():
    macs = c[0]
if macs:
    if "hmac-sha2-512" in macs.lower():
        print(f"assert: 1 strong MAC present")
    else:
        print(f"assert: 0 no strong MAC found")
else:
    print("assert: 0 MACs not configured")
CODE

regexp: :i ^^ \s* KexAlgorithms \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

kex = None
for c in captures():
    kex = c[0]
if kex:
    if "diffie-hellman" in kex.lower():
        print(f"assert: 1 DH KEX found")
    else:
        print(f"assert: 0 no DH KEX found")
else:
    print("assert: 0 KexAlgorithms not configured")
CODE

regexp: ^^ \s* HostKey \s+ ( \S+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

key = None
for c in captures():
    key = c[0]
if key:
    print(f"assert: 1 HostKey defined ({key})")
else:
    print("assert: 0 HostKey not found")
CODE

regexp: :i ^^ \s* SyslogFacility \s+ ( \S+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

fac = None
for c in captures():
    fac = c[0]
if fac:
    if fac.upper() in ("AUTH", "AUTHPRIV"):
        print(f"assert: 1 SyslogFacility {fac}")
    else:
        print(f"assert: 0 SyslogFacility {fac} (should be AUTH)")
else:
    print("assert: 0 SyslogFacility not set")
CODE

regexp: :i ^^ \s* LogLevel \s+ ( \S+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

level = None
for c in captures():
    level = c[0]
if level:
    if level.upper() in ("INFO", "VERBOSE", "DEBUG"):
        print(f"assert: 1 LogLevel {level}")
    else:
        print(f"assert: 0 LogLevel {level} (should be INFO or VERBOSE)")
else:
    print("assert: 0 LogLevel not set")
CODE

regexp: :i ^^ \s* AllowUsers \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

users_raw = None
for c in captures():
    users_raw = c[0]
if users_raw:
    user_list = users_raw.split()
    if user_list:
        print(f"assert: 1 AllowUsers restricts to {len(user_list)} user(s): {', '.join(user_list)}")
    else:
        print("assert: 0 AllowUsers has no users listed")
else:
    print("assert: 0 AllowUsers not set (open to all)")
CODE

regexp: :i ^^ \s* DenyUsers \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

users_raw = None
for c in captures():
    users_raw = c[0]
if users_raw:
    user_list = users_raw.split()
    if user_list:
        print(f"assert: 1 DenyUsers blocks {len(user_list)} user(s): {', '.join(user_list)}")
    else:
        print("assert: 0 DenyUsers has no users listed")
else:
    print("assert: 0 DenyUsers not set")
CODE

regexp: :i ^^ \s* AllowGroups \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

groups_raw = None
for c in captures():
    groups_raw = c[0]
if groups_raw:
    group_list = groups_raw.split()
    if group_list:
        print(f"assert: 1 AllowGroups restricts to {len(group_list)} group(s): {', '.join(group_list)}")
    else:
        print("assert: 0 AllowGroups has no groups listed")
else:
    print("assert: 0 AllowGroups not set")
CODE

regexp: :i ^^ \s* DenyGroups \s+ ( .+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

groups_raw = None
for c in captures():
    groups_raw = c[0]
if groups_raw:
    group_list = groups_raw.split()
    if group_list:
        print(f"assert: 1 DenyGroups blocks {len(group_list)} group(s): {', '.join(group_list)}")
    else:
        print("assert: 0 DenyGroups has no groups listed")
else:
    print("assert: 0 DenyGroups not set")
CODE

regexp: :i ^^ \s* Subsystem \s+ sftp \s+ ( \S+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

path = None
for c in captures():
    path = c[0]
if path:
    print(f"assert: 1 sftp subsystem defined ({path})")
else:
    print("assert: 0 sftp subsystem not defined")
CODE

regexp: ^^ \s* Banner \s+ ( \S+ ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

banner = None
for c in captures():
    banner = c[0]
if banner:
    print(f"assert: 1 Banner file {banner}")
else:
    print("assert: 0 Banner not set")
CODE

regexp: :i ^^ \s* Match \s+ ( Group \s+ \S+ | User \s+ \S+ | Host \s+ \S+ | Address \s+ \S+ | LocalAddress \s+ \S+ | LocalPort \s+ \S+ | All ) \s* $$
generator: <<CODE
!python
from sparrow6lib import *

match_val = None
for c in captures():
    match_val = c[0]
if match_val:
    print(f"assert: 1 Match block starts ({match_val})")
else:
    print("assert: 0 no Match block found")
CODE