mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
feat(sshd_config): Add indexes
This commit is contained in:
parent
47c511996b
commit
998c0740d1
@ -3,6 +3,7 @@ package analyzer
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/sshd_config"
|
||||
"config-lsp/handlers/sshd_config/indexes"
|
||||
"config-lsp/utils"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
@ -22,5 +23,19 @@ func Analyze(
|
||||
)
|
||||
}
|
||||
|
||||
indexes, indexErrors := indexes.CreateIndexes(*d.Config)
|
||||
_ = indexes
|
||||
|
||||
errors = append(errors, indexErrors...)
|
||||
|
||||
if len(errors) > 0 {
|
||||
return utils.Map(
|
||||
errors,
|
||||
func(err common.LSPError) protocol.Diagnostic {
|
||||
return err.ToDiagnostic()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ Match 192.168.0.2
|
||||
t.Errorf("Expected sixth entry to be 'MaxAuthTries 3', but got: %v", sixthEntry.Value)
|
||||
}
|
||||
|
||||
firstOption, firstMatchBlock := p.FindOption(uint32(4))
|
||||
firstOption, firstMatchBlock := p.FindOption(uint32(3))
|
||||
|
||||
if !(firstOption.Key.Value == "PasswordAuthentication" && firstOption.OptionValue.Value == "yes" && firstMatchBlock.MatchEntry.Value == "Match 192.168.0.1") {
|
||||
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)
|
||||
|
@ -103,7 +103,12 @@ func (c SSHConfig) FindOption(line uint32) (*SSHOption, *SSHMatchBlock) {
|
||||
rawEntry, found := c.Options.Get(line)
|
||||
|
||||
if found {
|
||||
return rawEntry.(*SSHOption), nil
|
||||
switch rawEntry.(type) {
|
||||
case *SSHMatchBlock:
|
||||
return rawEntry.(*SSHMatchBlock).MatchEntry, rawEntry.(*SSHMatchBlock)
|
||||
case *SSHOption:
|
||||
return rawEntry.(*SSHOption), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
88
handlers/sshd_config/indexes/indexes.go
Normal file
88
handlers/sshd_config/indexes/indexes.go
Normal file
@ -0,0 +1,88 @@
|
||||
package indexes
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var allowedDoubleOptions = map[string]struct{}{
|
||||
"AllowGroups": {},
|
||||
"AllowUsers": {},
|
||||
"DenyGroups": {},
|
||||
"DenyUsers": {},
|
||||
"ListenAddress": {},
|
||||
"Match": {},
|
||||
"Port": {},
|
||||
}
|
||||
|
||||
type SSHIndexEntry struct {
|
||||
Option string
|
||||
MatchBlock *ast.SSHMatchBlock
|
||||
}
|
||||
|
||||
type SSHIndexes struct {
|
||||
EntriesPerKey map[SSHIndexEntry][]*ast.SSHOption
|
||||
}
|
||||
|
||||
func CreateIndexes(config ast.SSHConfig) (*SSHIndexes, []common.LSPError) {
|
||||
errs := make([]common.LSPError, 0)
|
||||
indexes := &SSHIndexes{
|
||||
EntriesPerKey: make(map[SSHIndexEntry][]*ast.SSHOption),
|
||||
}
|
||||
|
||||
it := config.Options.Iterator()
|
||||
|
||||
for it.Next() {
|
||||
entry := it.Value().(ast.SSHEntry)
|
||||
|
||||
switch entry.(type) {
|
||||
case *ast.SSHOption:
|
||||
option := entry.(*ast.SSHOption)
|
||||
|
||||
errs = append(errs, addOption(indexes, option, nil)...)
|
||||
case *ast.SSHMatchBlock:
|
||||
matchBlock := entry.(*ast.SSHMatchBlock)
|
||||
|
||||
it := matchBlock.Options.Iterator()
|
||||
|
||||
for it.Next() {
|
||||
option := it.Value().(*ast.SSHOption)
|
||||
|
||||
errs = append(errs, addOption(indexes, option, matchBlock)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return indexes, errs
|
||||
}
|
||||
|
||||
func addOption(
|
||||
i *SSHIndexes,
|
||||
option *ast.SSHOption,
|
||||
matchBlock *ast.SSHMatchBlock,
|
||||
) []common.LSPError {
|
||||
var errs []common.LSPError
|
||||
|
||||
indexEntry := SSHIndexEntry{
|
||||
Option: option.Key.Value,
|
||||
MatchBlock: matchBlock,
|
||||
}
|
||||
|
||||
if existingEntry, found := i.EntriesPerKey[indexEntry]; found {
|
||||
if _, found := allowedDoubleOptions[option.Key.Value]; found {
|
||||
// Double value, but doubles are allowed
|
||||
i.EntriesPerKey[indexEntry] = append(existingEntry, option)
|
||||
} else {
|
||||
errs = append(errs, common.LSPError{
|
||||
Range: option.Key.LocationRange,
|
||||
Err: errors.New(fmt.Sprintf("Option %s is already defined on line %d", option.Key.Value, existingEntry[0].Start.Line+1)),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
i.EntriesPerKey[indexEntry] = []*ast.SSHOption{option}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
105
handlers/sshd_config/indexes/indexes_test.go
Normal file
105
handlers/sshd_config/indexes/indexes_test.go
Normal file
@ -0,0 +1,105 @@
|
||||
package indexes
|
||||
|
||||
import (
|
||||
"config-lsp/handlers/sshd_config/ast"
|
||||
"config-lsp/utils"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSimpleExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
PermitRootLogin yes
|
||||
RootLogin yes
|
||||
PermitRootLogin no
|
||||
`)
|
||||
config := ast.NewSSHConfig()
|
||||
errors := config.Parse(input)
|
||||
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("Unexpected errors: %v", errors)
|
||||
}
|
||||
|
||||
indexes, errors := CreateIndexes(*config)
|
||||
|
||||
if !(len(errors) == 1) {
|
||||
t.Fatalf("Expected 1 error, but got %v", len(errors))
|
||||
}
|
||||
|
||||
indexEntry := SSHIndexEntry{
|
||||
Option: "PermitRootLogin",
|
||||
MatchBlock: nil,
|
||||
}
|
||||
if !(indexes.EntriesPerKey[indexEntry][0].Value == "PermitRootLogin yes" && indexes.EntriesPerKey[indexEntry][0].Start.Line == 0) {
|
||||
t.Errorf("Expected 'PermitRootLogin yes', but got %v", indexes.EntriesPerKey[indexEntry][0].Value)
|
||||
}
|
||||
|
||||
indexEntry = SSHIndexEntry{
|
||||
Option: "RootLogin",
|
||||
MatchBlock: nil,
|
||||
}
|
||||
if !(indexes.EntriesPerKey[indexEntry][0].Value == "RootLogin yes" && indexes.EntriesPerKey[indexEntry][0].Start.Line == 1) {
|
||||
t.Errorf("Expected 'RootLogin yes', but got %v", indexes.EntriesPerKey[indexEntry][0].Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComplexExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
PermitRootLogin yes
|
||||
Port 22
|
||||
Port 2022
|
||||
Port 2024
|
||||
|
||||
Match Address 192.168.0.1/24
|
||||
PermitRootLogin no
|
||||
RoomLogin yes
|
||||
PermitRootLogin yes
|
||||
`)
|
||||
config := ast.NewSSHConfig()
|
||||
errors := config.Parse(input)
|
||||
|
||||
if len(errors) > 0 {
|
||||
t.Fatalf("Expected no errors, but got %v", len(errors))
|
||||
}
|
||||
|
||||
indexes, errors := CreateIndexes(*config)
|
||||
|
||||
if !(len(errors) == 1) {
|
||||
t.Fatalf("Expected no errors, but got %v", len(errors))
|
||||
}
|
||||
|
||||
indexEntry := SSHIndexEntry{
|
||||
Option: "PermitRootLogin",
|
||||
MatchBlock: nil,
|
||||
}
|
||||
if !(indexes.EntriesPerKey[indexEntry][0].Value == "PermitRootLogin yes" && indexes.EntriesPerKey[indexEntry][0].Start.Line == 0) {
|
||||
t.Errorf("Expected 'PermitRootLogin yes' on line 0, but got %v on line %v", indexes.EntriesPerKey[indexEntry][0].Value, indexes.EntriesPerKey[indexEntry][0].Start.Line)
|
||||
}
|
||||
|
||||
firstMatchBlock := config.FindMatchBlock(uint32(6))
|
||||
indexEntry = SSHIndexEntry{
|
||||
Option: "PermitRootLogin",
|
||||
MatchBlock: firstMatchBlock,
|
||||
}
|
||||
if !(indexes.EntriesPerKey[indexEntry][0].Value == "\tPermitRootLogin no" && indexes.EntriesPerKey[indexEntry][0].Start.Line == 6) {
|
||||
t.Errorf("Expected 'PermitRootLogin no' on line 6, but got %v on line %v", indexes.EntriesPerKey[indexEntry][0].Value, indexes.EntriesPerKey[indexEntry][0].Start.Line)
|
||||
}
|
||||
|
||||
// Double check
|
||||
indexEntry = SSHIndexEntry{
|
||||
Option: "Port",
|
||||
MatchBlock: nil,
|
||||
}
|
||||
if !(indexes.EntriesPerKey[indexEntry][0].Value == "Port 22" &&
|
||||
indexes.EntriesPerKey[indexEntry][0].Start.Line == 1 &&
|
||||
len(indexes.EntriesPerKey[indexEntry]) == 3 &&
|
||||
indexes.EntriesPerKey[indexEntry][1].Value == "Port 2022" &&
|
||||
indexes.EntriesPerKey[indexEntry][1].Start.Line == 2 &&
|
||||
indexes.EntriesPerKey[indexEntry][2].Value == "Port 2024" &&
|
||||
indexes.EntriesPerKey[indexEntry][2].Start.Line == 3) {
|
||||
t.Errorf("Expected 'Port 22' on line 1, but got %v on line %v", indexes.EntriesPerKey[indexEntry][0].Value, indexes.EntriesPerKey[indexEntry][0].Start.Line)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user