refactor(sshd_config): Improvements

This commit is contained in:
Myzel394 2024-09-26 20:25:01 +02:00
parent 07cb9ac045
commit 82301cf0cb
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
6 changed files with 134 additions and 34 deletions

View File

@ -2,7 +2,9 @@ package analyzer
import (
"config-lsp/common"
docvalues "config-lsp/doc-values"
sshdconfig "config-lsp/handlers/sshd_config"
"config-lsp/handlers/sshd_config/fields"
"config-lsp/handlers/sshd_config/match-parser"
"config-lsp/utils"
"errors"
@ -23,6 +25,7 @@ func analyzeMatchBlocks(
Range: option.LocationRange,
Err: errors.New("A match expression is required"),
})
continue
}
@ -32,12 +35,15 @@ func analyzeMatchBlocks(
Range: entry.LocationRange,
Err: errors.New(fmt.Sprintf("A value for %s is required", entry.Criteria.Type)),
})
} else {
errs = append(errs, analyzeMatchValuesContainsPositiveValue(entry.Values)...)
for _, value := range entry.Values.Values {
errs = append(errs, analyzeMatchValueNegation(value)...)
}
continue
}
errs = append(errs, analyzeMatchValuesContainsPositiveValue(entry.Values)...)
for _, value := range entry.Values.Values {
errs = append(errs, analyzeMatchValueNegation(value)...)
errs = append(errs, analyzeMatchValueIsValid(value, entry.Criteria.Type)...)
}
}
@ -109,3 +115,33 @@ func analyzeMatchValuesContainsPositiveValue(
return nil
}
func analyzeMatchValueIsValid(
value *matchparser.MatchValue,
criteria matchparser.MatchCriteriaType,
) []common.LSPError {
errs := make([]common.LSPError, 0)
if value.Value.Raw == "" {
return errs
}
docOption := fields.MatchValueFieldMap[criteria]
invalidValues := docOption.CheckIsValid(value.Value.Raw)
errs = append(
errs,
utils.Map(
invalidValues,
func(invalidValue *docvalues.InvalidValue) common.LSPError {
err := docvalues.LSPErrorFromInvalidValue(value.Start.Line, *invalidValue)
err.ShiftCharacter(value.Start.Character)
return err
},
)...,
)
return errs
}

View File

@ -61,3 +61,70 @@ Match User !root,!admin
t.Errorf("Expected 1 error, got %v", len(errors))
}
}
func TestEmptyMatchValues(
t *testing.T,
) {
input := utils.Dedent(`
PermitRootLogin yes
Match User
`)
c := ast.NewSSHDConfig()
errors := c.Parse(input)
if len(errors) > 0 {
t.Fatalf("Parse error: %v", errors)
}
i, errors := indexes.CreateIndexes(*c)
if len(errors) > 0 {
t.Fatalf("Index error: %v", errors)
}
d := &sshdconfig.SSHDDocument{
Config: c,
Indexes: i,
}
errors = analyzeMatchBlocks(d)
if !(len(errors) == 1) {
t.Errorf("Expected 1 error, got %v", len(errors))
}
}
func TestIncompleteMatchValues(
t *testing.T,
) {
input := utils.Dedent(`
PermitRootLogin yes
Match User
`)
c := ast.NewSSHDConfig()
errors := c.Parse(input)
if len(errors) > 0 {
t.Fatalf("Parse error: %v", errors)
}
i, errors := indexes.CreateIndexes(*c)
if len(errors) > 0 {
t.Fatalf("Index error: %v", errors)
}
d := &sshdconfig.SSHDDocument{
Config: c,
Indexes: i,
}
errors = analyzeMatchBlocks(d)
if !(len(errors) == 1) {
t.Errorf("Expected 1 error, got %v", len(errors))
}
}

View File

@ -109,24 +109,6 @@ func checkMatchBlock(
) []common.LSPError {
errs := make([]common.LSPError, 0)
matchOption := matchBlock.MatchOption.OptionValue
if matchOption != nil {
invalidValues := fields.Options["Match"].CheckIsValid(matchOption.Value.Value)
errs = append(
errs,
utils.Map(
invalidValues,
func(invalidValue *docvalues.InvalidValue) common.LSPError {
err := docvalues.LSPErrorFromInvalidValue(matchBlock.Start.Line, *invalidValue)
err.ShiftCharacter(matchOption.Start.Character)
return err
},
)...,
)
}
it := matchBlock.Options.Iterator()
for it.Next() {

View File

@ -10,16 +10,6 @@ var ZERO = 0
var MAX_PORT = 65535
var MAX_FILE_MODE = 0777
var AllowedDuplicateOptions = map[string]struct{}{
"AllowGroups": {},
"AllowUsers": {},
"DenyGroups": {},
"DenyUsers": {},
"ListenAddress": {},
"Match": {},
"Port": {},
}
var Options = map[string]docvalues.DocumentationValue{
"AcceptEnv": {
Documentation: `Specifies what environment variables sent by the client will be copied into the session's environ(7). See SendEnv and SetEnv in ssh_config(5) for how to configure the client. The TERM environment variable is always accepted whenever the client requests a pseudo-terminal as it is required by the protocol. Variables are specified by name, which may contain the wildcard characters * and ?. Multiple environment variables may be separated by whitespace or spread across multiple AcceptEnv directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be taken in the use of this directive. The default is not to accept any environment variables.`,

View File

@ -1,6 +1,9 @@
package fields
import docvalues "config-lsp/doc-values"
import (
docvalues "config-lsp/doc-values"
matchparser "config-lsp/handlers/sshd_config/match-parser"
)
var MatchAllowedOptions = map[string]struct{}{
"AcceptEnv": {},
@ -75,3 +78,13 @@ var MatchAddressField = docvalues.IPAddressValue{
AllowIPv6: true,
AllowRange: true,
}
var MatchValueFieldMap = map[matchparser.MatchCriteriaType]docvalues.Value{
matchparser.MatchCriteriaTypeUser: MatchUserField,
matchparser.MatchCriteriaTypeGroup: MatchGroupField,
matchparser.MatchCriteriaTypeHost: MatchHostField,
matchparser.MatchCriteriaTypeLocalAddress: MatchLocalAddressField,
matchparser.MatchCriteriaTypeLocalPort: MatchLocalPortField,
matchparser.MatchCriteriaTypeRDomain: MatchRDomainField,
matchparser.MatchCriteriaTypeAddress: MatchAddressField,
}

View File

@ -0,0 +1,12 @@
package fields
var AllowedDuplicateOptions = map[string]struct{}{
"AllowGroups": {},
"AllowUsers": {},
"DenyGroups": {},
"DenyUsers": {},
"ListenAddress": {},
"Match": {},
"Port": {},
}