feat(sshd_config): Parse match blocks inside the sshd_config parser

This commit is contained in:
Myzel394 2024-09-14 22:37:56 +02:00
parent 8118cf8092
commit 6911511b51
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
3 changed files with 52 additions and 22 deletions

View File

@ -3,9 +3,11 @@ package ast
import ( import (
"config-lsp/common" "config-lsp/common"
"config-lsp/handlers/sshd_config/ast/parser" "config-lsp/handlers/sshd_config/ast/parser"
match_parser "config-lsp/handlers/sshd_config/fields/match-parser"
"strings"
"github.com/emirpasic/gods/maps/treemap" "github.com/emirpasic/gods/maps/treemap"
gods "github.com/emirpasic/gods/utils" gods "github.com/emirpasic/gods/utils"
"strings"
) )
type sshListenerContext struct { type sshListenerContext struct {
@ -93,17 +95,31 @@ func (s *sshParserListener) ExitEntry(ctx *parser.EntryContext) {
if s.sshContext.isKeyAMatchBlock { if s.sshContext.isKeyAMatchBlock {
// Add new match block // Add new match block
matchBlock := &SSHMatchBlock{ match := match_parser.NewMatch()
LocationRange: location, errors := match.Parse(s.sshContext.currentOption.OptionValue.Value, location.Start.Line)
MatchEntry: s.sshContext.currentOption,
Options: treemap.NewWith(gods.UInt32Comparator), if len(errors) > 0 {
} for _, err := range errors {
s.Config.Options.Put( s.Errors = append(s.Errors, common.LSPError{
location.Start.Line, Range: err.Range.ShiftHorizontal(s.sshContext.currentOption.Start.Character),
matchBlock, Err: err.Err,
) })
}
} else {
matchBlock := &SSHMatchBlock{
LocationRange: location,
MatchEntry: s.sshContext.currentOption,
MatchValue: match,
Options: treemap.NewWith(gods.UInt32Comparator),
}
s.Config.Options.Put(
location.Start.Line,
matchBlock,
)
s.sshContext.currentMatchBlock = matchBlock
}
s.sshContext.currentMatchBlock = matchBlock
s.sshContext.isKeyAMatchBlock = false s.sshContext.isKeyAMatchBlock = false
} else if s.sshContext.currentMatchBlock != nil { } else if s.sshContext.currentMatchBlock != nil {
s.sshContext.currentMatchBlock.Options.Put( s.sshContext.currentMatchBlock.Options.Put(

View File

@ -65,7 +65,7 @@ func TestMatchSimpleBlock(
input := utils.Dedent(` input := utils.Dedent(`
PermitRootLogin no PermitRootLogin no
Match 192.168.0.1 Match Address 192.168.0.1
PasswordAuthentication yes PasswordAuthentication yes
`) `)
p := NewSSHConfig() p := NewSSHConfig()
@ -88,8 +88,12 @@ Match 192.168.0.1
rawSecondEntry, _ := p.Options.Get(uint32(2)) rawSecondEntry, _ := p.Options.Get(uint32(2))
secondEntry := rawSecondEntry.(*SSHMatchBlock) secondEntry := rawSecondEntry.(*SSHMatchBlock)
if !(secondEntry.MatchEntry.Value == "Match 192.168.0.1") { if !(secondEntry.MatchEntry.Value == "Match Address 192.168.0.1") {
t.Errorf("Expected second entry to be 'Match 192.168.0.1', but got: %v", secondEntry.MatchEntry.Value) t.Errorf("Expected second entry to be 'Match Address 192.168.0.1', but got: %v", secondEntry.MatchEntry.Value)
}
if !(secondEntry.MatchValue.Entries[0].Criteria == "Address" && secondEntry.MatchValue.Entries[0].Values[0].Value == "192.168.0.1") {
t.Errorf("Expected second entry to be 'Match Address 192.168.0.1', but got: %v", secondEntry.MatchValue)
} }
if !(secondEntry.Options.Size() == 1) { if !(secondEntry.Options.Size() == 1) {
@ -109,11 +113,11 @@ func TestMultipleMatchBlocks(
input := utils.Dedent(` input := utils.Dedent(`
PermitRootLogin no PermitRootLogin no
Match 192.168.0.1 Match User lena
PasswordAuthentication yes PasswordAuthentication yes
AllowUsers root user AllowUsers root user
Match 192.168.0.2 Match Address 192.168.0.2
MaxAuthTries 3 MaxAuthTries 3
`) `)
p := NewSSHConfig() p := NewSSHConfig()
@ -159,18 +163,18 @@ Match 192.168.0.2
} }
firstOption, firstMatchBlock := p.FindOption(uint32(3)) firstOption, firstMatchBlock := p.FindOption(uint32(3))
if !(firstOption.Key.Value == "PasswordAuthentication" && firstOption.OptionValue.Value == "yes" && firstMatchBlock.MatchEntry.Value == "Match 192.168.0.1") { if !(firstOption.Key.Value == "PasswordAuthentication" && firstOption.OptionValue.Value == "yes") {
t.Errorf("Expected first option to be 'PasswordAuthentication yes' and first match block to be 'Match 192.168.0.1', but got: %v, %v", firstOption, firstMatchBlock) t.Errorf("Expected first option to be 'PasswordAuthentication yes' and first match block to be 'Match Address 192.168.0.1', but got: %v, %v", firstOption, firstMatchBlock)
} }
emptyOption, matchBlock := p.FindOption(uint32(5)) emptyOption, matchBlock := p.FindOption(uint32(5))
if !(emptyOption == nil && matchBlock.MatchEntry.Value == "Match 192.168.0.1") { if !(emptyOption == nil && matchBlock.MatchEntry.Value == "Match User lena" && matchBlock.MatchValue.Entries[0].Values[0].Value == "lena") {
t.Errorf("Expected empty option and match block to be 'Match 192.168.0.1', but got: %v, %v", emptyOption, matchBlock) t.Errorf("Expected empty option and match block to be 'Match User lena', but got: %v, %v", emptyOption, matchBlock)
} }
matchOption, matchBlock := p.FindOption(uint32(2)) matchOption, matchBlock := p.FindOption(uint32(2))
if !(matchOption.Value == "Match 192.168.0.1" && matchBlock.MatchEntry.Value == "Match 192.168.0.1") { if !(matchOption.Value == "Match User lena" && matchBlock.MatchEntry.Value == "Match User lena" && matchBlock.MatchValue.Entries[0].Values[0].Value == "lena") {
t.Errorf("Expected match option to be 'Match 192.160.0.1' and match block to be 'Match 192.168.0.1', but got: %v, %v", matchOption, matchBlock) t.Errorf("Expected match option to be 'Match User lena', but got: %v, %v", matchOption, matchBlock)
} }
} }
@ -412,6 +416,10 @@ Match Address 172.22.100.0/24,172.22.5.0/24,127.0.0.1
t.Errorf("Expected fourth entry to be 'Match User anoncvs', but got: %v", fourthEntry.MatchEntry.Value) t.Errorf("Expected fourth entry to be 'Match User anoncvs', but got: %v", fourthEntry.MatchEntry.Value)
} }
if !(fourthEntry.MatchValue.Entries[0].Criteria == "User" && fourthEntry.MatchValue.Entries[0].Values[0].Value == "anoncvs") {
t.Errorf("Expected fourth entry to be 'Match User anoncvs', but got: %v", fourthEntry.MatchValue)
}
if !(fourthEntry.Options.Size() == 3) { if !(fourthEntry.Options.Size() == 3) {
t.Errorf("Expected 3 options in fourth match block, but got: %v", fourthEntry.Options) t.Errorf("Expected 3 options in fourth match block, but got: %v", fourthEntry.Options)
} }
@ -432,6 +440,10 @@ Match Address 172.22.100.0/24,172.22.5.0/24,127.0.0.1
t.Errorf("Expected sixth entry to be 'Match Address 172.22.100.0/24,172.22.5.0/24,127.0.0.1', but got: %v", sixthEntry.MatchEntry.Value) t.Errorf("Expected sixth entry to be 'Match Address 172.22.100.0/24,172.22.5.0/24,127.0.0.1', but got: %v", sixthEntry.MatchEntry.Value)
} }
if !(sixthEntry.MatchValue.Entries[0].Criteria == "Address" && len(sixthEntry.MatchValue.Entries[0].Values) == 3) {
t.Errorf("Expected sixth entry to contain 3 values, but got: %v", sixthEntry.MatchValue)
}
if !(sixthEntry.Options.Size() == 2) { if !(sixthEntry.Options.Size() == 2) {
t.Errorf("Expected 2 options in sixth match block, but got: %v", sixthEntry.Options) t.Errorf("Expected 2 options in sixth match block, but got: %v", sixthEntry.Options)
} }

View File

@ -2,6 +2,7 @@ package ast
import ( import (
"config-lsp/common" "config-lsp/common"
match_parser "config-lsp/handlers/sshd_config/fields/match-parser"
"github.com/emirpasic/gods/maps/treemap" "github.com/emirpasic/gods/maps/treemap"
) )
@ -52,6 +53,7 @@ func (o SSHOption) GetOption() SSHOption {
type SSHMatchBlock struct { type SSHMatchBlock struct {
common.LocationRange common.LocationRange
MatchEntry *SSHOption MatchEntry *SSHOption
MatchValue *match_parser.Match
// [uint32]*SSHOption -> line number -> *SSHOption // [uint32]*SSHOption -> line number -> *SSHOption
Options *treemap.Map Options *treemap.Map