mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-19 07:25:27 +02:00
fix(sshd_config): Improve parser
This commit is contained in:
parent
82797de8e5
commit
93203a7179
@ -13,22 +13,17 @@ key
|
|||||||
;
|
;
|
||||||
|
|
||||||
value
|
value
|
||||||
: STRING
|
: (STRING WHITESPACE)? STRING
|
||||||
;
|
;
|
||||||
|
|
||||||
leadingComment
|
leadingComment
|
||||||
: HASH WHITESPACE? (STRING WHITESPACE?)+
|
: HASH WHITESPACE? (STRING WHITESPACE?)+
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
HASH
|
HASH
|
||||||
: '#'
|
: '#'
|
||||||
;
|
;
|
||||||
|
|
||||||
MATCH
|
|
||||||
: ('M' | 'm') ('A' | 'a') ('T' | 't') ('C' | 'c') ('H' | 'h')
|
|
||||||
;
|
|
||||||
|
|
||||||
WHITESPACE
|
WHITESPACE
|
||||||
: [ \t]+
|
: [ \t]+
|
||||||
;
|
;
|
||||||
|
@ -3,6 +3,8 @@ package ast
|
|||||||
import (
|
import (
|
||||||
"config-lsp/common"
|
"config-lsp/common"
|
||||||
"config-lsp/handlers/sshd_config/ast/parser"
|
"config-lsp/handlers/sshd_config/ast/parser"
|
||||||
|
"github.com/emirpasic/gods/maps/treemap"
|
||||||
|
gods "github.com/emirpasic/gods/utils"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,21 +49,7 @@ func (s *sshParserListener) EnterEntry(ctx *parser.EntryContext) {
|
|||||||
Value: ctx.GetText(),
|
Value: ctx.GetText(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.sshContext.currentMatchBlock == nil {
|
|
||||||
s.Config.Options.Put(
|
|
||||||
location.Start.Line,
|
|
||||||
option,
|
|
||||||
)
|
|
||||||
|
|
||||||
s.sshContext.currentOption = option
|
s.sshContext.currentOption = option
|
||||||
} else {
|
|
||||||
s.sshContext.currentMatchBlock.Options.Put(
|
|
||||||
location.Start.Line,
|
|
||||||
option,
|
|
||||||
)
|
|
||||||
|
|
||||||
s.sshContext.currentOption = option
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sshParserListener) EnterKey(ctx *parser.KeyContext) {
|
func (s *sshParserListener) EnterKey(ctx *parser.KeyContext) {
|
||||||
@ -91,17 +79,16 @@ func (s *sshParserListener) EnterValue(ctx *parser.ValueContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *sshParserListener) ExitValue(ctx *parser.ValueContext) {
|
func (s *sshParserListener) ExitValue(ctx *parser.ValueContext) {
|
||||||
if s.sshContext.isKeyAMatchBlock {
|
|
||||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||||
location.ChangeBothLines(s.sshContext.line)
|
location.ChangeBothLines(s.sshContext.line)
|
||||||
|
|
||||||
rawEntry, _ := s.Config.Options.Get(location.Start.Line)
|
|
||||||
entry := rawEntry.(*SSHOption)
|
|
||||||
|
|
||||||
// Overwrite the current match block
|
if s.sshContext.isKeyAMatchBlock {
|
||||||
|
// Add new match block
|
||||||
matchBlock := &SSHMatchBlock{
|
matchBlock := &SSHMatchBlock{
|
||||||
LocationRange: location,
|
LocationRange: location,
|
||||||
MatchEntry: entry,
|
MatchEntry: s.sshContext.currentOption,
|
||||||
|
Options: treemap.NewWith(gods.UInt32Comparator),
|
||||||
}
|
}
|
||||||
s.Config.Options.Put(
|
s.Config.Options.Put(
|
||||||
location.Start.Line,
|
location.Start.Line,
|
||||||
@ -110,6 +97,16 @@ func (s *sshParserListener) ExitValue(ctx *parser.ValueContext) {
|
|||||||
|
|
||||||
s.sshContext.currentMatchBlock = matchBlock
|
s.sshContext.currentMatchBlock = matchBlock
|
||||||
s.sshContext.isKeyAMatchBlock = false
|
s.sshContext.isKeyAMatchBlock = false
|
||||||
|
} else if s.sshContext.currentMatchBlock != nil {
|
||||||
|
s.sshContext.currentMatchBlock.Options.Put(
|
||||||
|
location.Start.Line,
|
||||||
|
s.sshContext.currentOption,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
s.Config.Options.Put(
|
||||||
|
location.Start.Line,
|
||||||
|
s.sshContext.currentOption,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.sshContext.currentOption = nil
|
s.sshContext.currentOption = nil
|
||||||
|
@ -35,12 +35,12 @@ func (c *SSHConfig) Parse(input string) []common.LSPError {
|
|||||||
for rawLineNumber, line := range lines {
|
for rawLineNumber, line := range lines {
|
||||||
context.line = uint32(rawLineNumber)
|
context.line = uint32(rawLineNumber)
|
||||||
|
|
||||||
if commentPattern.MatchString(line) {
|
if emptyPattern.MatchString(line) {
|
||||||
c.CommentLines[context.line] = struct{}{}
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if emptyPattern.MatchString(line) {
|
if commentPattern.MatchString(line) {
|
||||||
|
c.CommentLines[context.line] = struct{}{}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,10 @@ null
|
|||||||
null
|
null
|
||||||
null
|
null
|
||||||
null
|
null
|
||||||
null
|
|
||||||
|
|
||||||
token symbolic names:
|
token symbolic names:
|
||||||
null
|
null
|
||||||
HASH
|
HASH
|
||||||
MATCH
|
|
||||||
WHITESPACE
|
WHITESPACE
|
||||||
STRING
|
STRING
|
||||||
NEWLINE
|
NEWLINE
|
||||||
@ -23,4 +21,4 @@ leadingComment
|
|||||||
|
|
||||||
|
|
||||||
atn:
|
atn:
|
||||||
[4, 1, 5, 55, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 1, 0, 1, 0, 3, 0, 13, 8, 0, 1, 0, 1, 0, 3, 0, 17, 8, 0, 3, 0, 19, 8, 0, 1, 0, 1, 0, 1, 1, 3, 1, 24, 8, 1, 1, 1, 3, 1, 27, 8, 1, 1, 1, 1, 1, 3, 1, 31, 8, 1, 1, 1, 3, 1, 34, 8, 1, 1, 1, 3, 1, 37, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 3, 4, 45, 8, 4, 1, 4, 1, 4, 3, 4, 49, 8, 4, 4, 4, 51, 8, 4, 11, 4, 12, 4, 52, 1, 4, 0, 0, 5, 0, 2, 4, 6, 8, 0, 0, 61, 0, 18, 1, 0, 0, 0, 2, 23, 1, 0, 0, 0, 4, 38, 1, 0, 0, 0, 6, 40, 1, 0, 0, 0, 8, 42, 1, 0, 0, 0, 10, 19, 3, 2, 1, 0, 11, 13, 5, 3, 0, 0, 12, 11, 1, 0, 0, 0, 12, 13, 1, 0, 0, 0, 13, 14, 1, 0, 0, 0, 14, 19, 3, 8, 4, 0, 15, 17, 5, 3, 0, 0, 16, 15, 1, 0, 0, 0, 16, 17, 1, 0, 0, 0, 17, 19, 1, 0, 0, 0, 18, 10, 1, 0, 0, 0, 18, 12, 1, 0, 0, 0, 18, 16, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 21, 5, 0, 0, 1, 21, 1, 1, 0, 0, 0, 22, 24, 5, 3, 0, 0, 23, 22, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 26, 1, 0, 0, 0, 25, 27, 3, 4, 2, 0, 26, 25, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 5, 3, 0, 0, 29, 31, 3, 6, 3, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 33, 1, 0, 0, 0, 32, 34, 5, 3, 0, 0, 33, 32, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 37, 3, 8, 4, 0, 36, 35, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 3, 1, 0, 0, 0, 38, 39, 5, 4, 0, 0, 39, 5, 1, 0, 0, 0, 40, 41, 5, 4, 0, 0, 41, 7, 1, 0, 0, 0, 42, 44, 5, 1, 0, 0, 43, 45, 5, 3, 0, 0, 44, 43, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 50, 1, 0, 0, 0, 46, 48, 5, 4, 0, 0, 47, 49, 5, 3, 0, 0, 48, 47, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 51, 1, 0, 0, 0, 50, 46, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 50, 1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 9, 1, 0, 0, 0, 11, 12, 16, 18, 23, 26, 30, 33, 36, 44, 48, 52]
|
[4, 1, 4, 59, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 1, 0, 1, 0, 3, 0, 13, 8, 0, 1, 0, 1, 0, 3, 0, 17, 8, 0, 3, 0, 19, 8, 0, 1, 0, 1, 0, 1, 1, 3, 1, 24, 8, 1, 1, 1, 3, 1, 27, 8, 1, 1, 1, 1, 1, 3, 1, 31, 8, 1, 1, 1, 3, 1, 34, 8, 1, 1, 1, 3, 1, 37, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 3, 3, 43, 8, 3, 1, 3, 1, 3, 1, 4, 1, 4, 3, 4, 49, 8, 4, 1, 4, 1, 4, 3, 4, 53, 8, 4, 4, 4, 55, 8, 4, 11, 4, 12, 4, 56, 1, 4, 0, 0, 5, 0, 2, 4, 6, 8, 0, 0, 66, 0, 18, 1, 0, 0, 0, 2, 23, 1, 0, 0, 0, 4, 38, 1, 0, 0, 0, 6, 42, 1, 0, 0, 0, 8, 46, 1, 0, 0, 0, 10, 19, 3, 2, 1, 0, 11, 13, 5, 2, 0, 0, 12, 11, 1, 0, 0, 0, 12, 13, 1, 0, 0, 0, 13, 14, 1, 0, 0, 0, 14, 19, 3, 8, 4, 0, 15, 17, 5, 2, 0, 0, 16, 15, 1, 0, 0, 0, 16, 17, 1, 0, 0, 0, 17, 19, 1, 0, 0, 0, 18, 10, 1, 0, 0, 0, 18, 12, 1, 0, 0, 0, 18, 16, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 21, 5, 0, 0, 1, 21, 1, 1, 0, 0, 0, 22, 24, 5, 2, 0, 0, 23, 22, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 26, 1, 0, 0, 0, 25, 27, 3, 4, 2, 0, 26, 25, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 5, 2, 0, 0, 29, 31, 3, 6, 3, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 33, 1, 0, 0, 0, 32, 34, 5, 2, 0, 0, 33, 32, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 37, 3, 8, 4, 0, 36, 35, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 3, 1, 0, 0, 0, 38, 39, 5, 3, 0, 0, 39, 5, 1, 0, 0, 0, 40, 41, 5, 3, 0, 0, 41, 43, 5, 2, 0, 0, 42, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 45, 5, 3, 0, 0, 45, 7, 1, 0, 0, 0, 46, 48, 5, 1, 0, 0, 47, 49, 5, 2, 0, 0, 48, 47, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 54, 1, 0, 0, 0, 50, 52, 5, 3, 0, 0, 51, 53, 5, 2, 0, 0, 52, 51, 1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 55, 1, 0, 0, 0, 54, 50, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 9, 1, 0, 0, 0, 12, 12, 16, 18, 23, 26, 30, 33, 36, 42, 48, 52, 56]
|
@ -1,6 +1,5 @@
|
|||||||
HASH=1
|
HASH=1
|
||||||
MATCH=2
|
WHITESPACE=2
|
||||||
WHITESPACE=3
|
STRING=3
|
||||||
STRING=4
|
NEWLINE=4
|
||||||
NEWLINE=5
|
|
||||||
'#'=1
|
'#'=1
|
||||||
|
@ -4,19 +4,16 @@ null
|
|||||||
null
|
null
|
||||||
null
|
null
|
||||||
null
|
null
|
||||||
null
|
|
||||||
|
|
||||||
token symbolic names:
|
token symbolic names:
|
||||||
null
|
null
|
||||||
HASH
|
HASH
|
||||||
MATCH
|
|
||||||
WHITESPACE
|
WHITESPACE
|
||||||
STRING
|
STRING
|
||||||
NEWLINE
|
NEWLINE
|
||||||
|
|
||||||
rule names:
|
rule names:
|
||||||
HASH
|
HASH
|
||||||
MATCH
|
|
||||||
WHITESPACE
|
WHITESPACE
|
||||||
STRING
|
STRING
|
||||||
NEWLINE
|
NEWLINE
|
||||||
@ -29,4 +26,4 @@ mode names:
|
|||||||
DEFAULT_MODE
|
DEFAULT_MODE
|
||||||
|
|
||||||
atn:
|
atn:
|
||||||
[4, 0, 5, 34, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 21, 8, 2, 11, 2, 12, 2, 22, 1, 3, 4, 3, 26, 8, 3, 11, 3, 12, 3, 27, 1, 4, 3, 4, 31, 8, 4, 1, 4, 1, 4, 0, 0, 5, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 0, 7, 2, 0, 77, 77, 109, 109, 2, 0, 65, 65, 97, 97, 2, 0, 84, 84, 116, 116, 2, 0, 67, 67, 99, 99, 2, 0, 72, 72, 104, 104, 2, 0, 9, 9, 32, 32, 4, 0, 9, 10, 13, 13, 32, 32, 35, 35, 36, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 1, 11, 1, 0, 0, 0, 3, 13, 1, 0, 0, 0, 5, 20, 1, 0, 0, 0, 7, 25, 1, 0, 0, 0, 9, 30, 1, 0, 0, 0, 11, 12, 5, 35, 0, 0, 12, 2, 1, 0, 0, 0, 13, 14, 7, 0, 0, 0, 14, 15, 7, 1, 0, 0, 15, 16, 7, 2, 0, 0, 16, 17, 7, 3, 0, 0, 17, 18, 7, 4, 0, 0, 18, 4, 1, 0, 0, 0, 19, 21, 7, 5, 0, 0, 20, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 6, 1, 0, 0, 0, 24, 26, 8, 6, 0, 0, 25, 24, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 25, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 8, 1, 0, 0, 0, 29, 31, 5, 13, 0, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 33, 5, 10, 0, 0, 33, 10, 1, 0, 0, 0, 4, 0, 22, 27, 30, 0]
|
[4, 0, 4, 26, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 1, 0, 1, 0, 1, 1, 4, 1, 13, 8, 1, 11, 1, 12, 1, 14, 1, 2, 4, 2, 18, 8, 2, 11, 2, 12, 2, 19, 1, 3, 3, 3, 23, 8, 3, 1, 3, 1, 3, 0, 0, 4, 1, 1, 3, 2, 5, 3, 7, 4, 1, 0, 2, 2, 0, 9, 9, 32, 32, 4, 0, 9, 10, 13, 13, 32, 32, 35, 35, 28, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 1, 9, 1, 0, 0, 0, 3, 12, 1, 0, 0, 0, 5, 17, 1, 0, 0, 0, 7, 22, 1, 0, 0, 0, 9, 10, 5, 35, 0, 0, 10, 2, 1, 0, 0, 0, 11, 13, 7, 0, 0, 0, 12, 11, 1, 0, 0, 0, 13, 14, 1, 0, 0, 0, 14, 12, 1, 0, 0, 0, 14, 15, 1, 0, 0, 0, 15, 4, 1, 0, 0, 0, 16, 18, 8, 1, 0, 0, 17, 16, 1, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 6, 1, 0, 0, 0, 21, 23, 5, 13, 0, 0, 22, 21, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 25, 5, 10, 0, 0, 25, 8, 1, 0, 0, 0, 4, 0, 14, 19, 22, 0]
|
@ -1,6 +1,5 @@
|
|||||||
HASH=1
|
HASH=1
|
||||||
MATCH=2
|
WHITESPACE=2
|
||||||
WHITESPACE=3
|
STRING=3
|
||||||
STRING=4
|
NEWLINE=4
|
||||||
NEWLINE=5
|
|
||||||
'#'=1
|
'#'=1
|
||||||
|
@ -46,30 +46,25 @@ func configlexerLexerInit() {
|
|||||||
"", "'#'",
|
"", "'#'",
|
||||||
}
|
}
|
||||||
staticData.SymbolicNames = []string{
|
staticData.SymbolicNames = []string{
|
||||||
"", "HASH", "MATCH", "WHITESPACE", "STRING", "NEWLINE",
|
"", "HASH", "WHITESPACE", "STRING", "NEWLINE",
|
||||||
}
|
}
|
||||||
staticData.RuleNames = []string{
|
staticData.RuleNames = []string{
|
||||||
"HASH", "MATCH", "WHITESPACE", "STRING", "NEWLINE",
|
"HASH", "WHITESPACE", "STRING", "NEWLINE",
|
||||||
}
|
}
|
||||||
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
||||||
staticData.serializedATN = []int32{
|
staticData.serializedATN = []int32{
|
||||||
4, 0, 5, 34, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
|
4, 0, 4, 26, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 1,
|
||||||
4, 7, 4, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 2, 21,
|
0, 1, 0, 1, 1, 4, 1, 13, 8, 1, 11, 1, 12, 1, 14, 1, 2, 4, 2, 18, 8, 2,
|
||||||
8, 2, 11, 2, 12, 2, 22, 1, 3, 4, 3, 26, 8, 3, 11, 3, 12, 3, 27, 1, 4, 3,
|
11, 2, 12, 2, 19, 1, 3, 3, 3, 23, 8, 3, 1, 3, 1, 3, 0, 0, 4, 1, 1, 3, 2,
|
||||||
4, 31, 8, 4, 1, 4, 1, 4, 0, 0, 5, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 1, 0, 7,
|
5, 3, 7, 4, 1, 0, 2, 2, 0, 9, 9, 32, 32, 4, 0, 9, 10, 13, 13, 32, 32, 35,
|
||||||
2, 0, 77, 77, 109, 109, 2, 0, 65, 65, 97, 97, 2, 0, 84, 84, 116, 116, 2,
|
35, 28, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1,
|
||||||
0, 67, 67, 99, 99, 2, 0, 72, 72, 104, 104, 2, 0, 9, 9, 32, 32, 4, 0, 9,
|
0, 0, 0, 1, 9, 1, 0, 0, 0, 3, 12, 1, 0, 0, 0, 5, 17, 1, 0, 0, 0, 7, 22,
|
||||||
10, 13, 13, 32, 32, 35, 35, 36, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0,
|
1, 0, 0, 0, 9, 10, 5, 35, 0, 0, 10, 2, 1, 0, 0, 0, 11, 13, 7, 0, 0, 0,
|
||||||
5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 1, 11, 1, 0, 0, 0, 3,
|
12, 11, 1, 0, 0, 0, 13, 14, 1, 0, 0, 0, 14, 12, 1, 0, 0, 0, 14, 15, 1,
|
||||||
13, 1, 0, 0, 0, 5, 20, 1, 0, 0, 0, 7, 25, 1, 0, 0, 0, 9, 30, 1, 0, 0, 0,
|
0, 0, 0, 15, 4, 1, 0, 0, 0, 16, 18, 8, 1, 0, 0, 17, 16, 1, 0, 0, 0, 18,
|
||||||
11, 12, 5, 35, 0, 0, 12, 2, 1, 0, 0, 0, 13, 14, 7, 0, 0, 0, 14, 15, 7,
|
19, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 6, 1, 0, 0,
|
||||||
1, 0, 0, 15, 16, 7, 2, 0, 0, 16, 17, 7, 3, 0, 0, 17, 18, 7, 4, 0, 0, 18,
|
0, 21, 23, 5, 13, 0, 0, 22, 21, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 24,
|
||||||
4, 1, 0, 0, 0, 19, 21, 7, 5, 0, 0, 20, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0,
|
1, 0, 0, 0, 24, 25, 5, 10, 0, 0, 25, 8, 1, 0, 0, 0, 4, 0, 14, 19, 22, 0,
|
||||||
0, 22, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 6, 1, 0, 0, 0, 24, 26, 8,
|
|
||||||
6, 0, 0, 25, 24, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 25, 1, 0, 0, 0, 27,
|
|
||||||
28, 1, 0, 0, 0, 28, 8, 1, 0, 0, 0, 29, 31, 5, 13, 0, 0, 30, 29, 1, 0, 0,
|
|
||||||
0, 30, 31, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 33, 5, 10, 0, 0, 33, 10,
|
|
||||||
1, 0, 0, 0, 4, 0, 22, 27, 30, 0,
|
|
||||||
}
|
}
|
||||||
deserializer := antlr.NewATNDeserializer(nil)
|
deserializer := antlr.NewATNDeserializer(nil)
|
||||||
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
||||||
@ -111,8 +106,7 @@ func NewConfigLexer(input antlr.CharStream) *ConfigLexer {
|
|||||||
// ConfigLexer tokens.
|
// ConfigLexer tokens.
|
||||||
const (
|
const (
|
||||||
ConfigLexerHASH = 1
|
ConfigLexerHASH = 1
|
||||||
ConfigLexerMATCH = 2
|
ConfigLexerWHITESPACE = 2
|
||||||
ConfigLexerWHITESPACE = 3
|
ConfigLexerSTRING = 3
|
||||||
ConfigLexerSTRING = 4
|
ConfigLexerNEWLINE = 4
|
||||||
ConfigLexerNEWLINE = 5
|
|
||||||
)
|
)
|
||||||
|
@ -36,37 +36,39 @@ func configParserInit() {
|
|||||||
"", "'#'",
|
"", "'#'",
|
||||||
}
|
}
|
||||||
staticData.SymbolicNames = []string{
|
staticData.SymbolicNames = []string{
|
||||||
"", "HASH", "MATCH", "WHITESPACE", "STRING", "NEWLINE",
|
"", "HASH", "WHITESPACE", "STRING", "NEWLINE",
|
||||||
}
|
}
|
||||||
staticData.RuleNames = []string{
|
staticData.RuleNames = []string{
|
||||||
"lineStatement", "entry", "key", "value", "leadingComment",
|
"lineStatement", "entry", "key", "value", "leadingComment",
|
||||||
}
|
}
|
||||||
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
||||||
staticData.serializedATN = []int32{
|
staticData.serializedATN = []int32{
|
||||||
4, 1, 5, 55, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4,
|
4, 1, 4, 59, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4,
|
||||||
1, 0, 1, 0, 3, 0, 13, 8, 0, 1, 0, 1, 0, 3, 0, 17, 8, 0, 3, 0, 19, 8, 0,
|
1, 0, 1, 0, 3, 0, 13, 8, 0, 1, 0, 1, 0, 3, 0, 17, 8, 0, 3, 0, 19, 8, 0,
|
||||||
1, 0, 1, 0, 1, 1, 3, 1, 24, 8, 1, 1, 1, 3, 1, 27, 8, 1, 1, 1, 1, 1, 3,
|
1, 0, 1, 0, 1, 1, 3, 1, 24, 8, 1, 1, 1, 3, 1, 27, 8, 1, 1, 1, 1, 1, 3,
|
||||||
1, 31, 8, 1, 1, 1, 3, 1, 34, 8, 1, 1, 1, 3, 1, 37, 8, 1, 1, 2, 1, 2, 1,
|
1, 31, 8, 1, 1, 1, 3, 1, 34, 8, 1, 1, 1, 3, 1, 37, 8, 1, 1, 2, 1, 2, 1,
|
||||||
3, 1, 3, 1, 4, 1, 4, 3, 4, 45, 8, 4, 1, 4, 1, 4, 3, 4, 49, 8, 4, 4, 4,
|
3, 1, 3, 3, 3, 43, 8, 3, 1, 3, 1, 3, 1, 4, 1, 4, 3, 4, 49, 8, 4, 1, 4,
|
||||||
51, 8, 4, 11, 4, 12, 4, 52, 1, 4, 0, 0, 5, 0, 2, 4, 6, 8, 0, 0, 61, 0,
|
1, 4, 3, 4, 53, 8, 4, 4, 4, 55, 8, 4, 11, 4, 12, 4, 56, 1, 4, 0, 0, 5,
|
||||||
18, 1, 0, 0, 0, 2, 23, 1, 0, 0, 0, 4, 38, 1, 0, 0, 0, 6, 40, 1, 0, 0, 0,
|
0, 2, 4, 6, 8, 0, 0, 66, 0, 18, 1, 0, 0, 0, 2, 23, 1, 0, 0, 0, 4, 38, 1,
|
||||||
8, 42, 1, 0, 0, 0, 10, 19, 3, 2, 1, 0, 11, 13, 5, 3, 0, 0, 12, 11, 1, 0,
|
0, 0, 0, 6, 42, 1, 0, 0, 0, 8, 46, 1, 0, 0, 0, 10, 19, 3, 2, 1, 0, 11,
|
||||||
0, 0, 12, 13, 1, 0, 0, 0, 13, 14, 1, 0, 0, 0, 14, 19, 3, 8, 4, 0, 15, 17,
|
13, 5, 2, 0, 0, 12, 11, 1, 0, 0, 0, 12, 13, 1, 0, 0, 0, 13, 14, 1, 0, 0,
|
||||||
5, 3, 0, 0, 16, 15, 1, 0, 0, 0, 16, 17, 1, 0, 0, 0, 17, 19, 1, 0, 0, 0,
|
0, 14, 19, 3, 8, 4, 0, 15, 17, 5, 2, 0, 0, 16, 15, 1, 0, 0, 0, 16, 17,
|
||||||
18, 10, 1, 0, 0, 0, 18, 12, 1, 0, 0, 0, 18, 16, 1, 0, 0, 0, 19, 20, 1,
|
1, 0, 0, 0, 17, 19, 1, 0, 0, 0, 18, 10, 1, 0, 0, 0, 18, 12, 1, 0, 0, 0,
|
||||||
0, 0, 0, 20, 21, 5, 0, 0, 1, 21, 1, 1, 0, 0, 0, 22, 24, 5, 3, 0, 0, 23,
|
18, 16, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 21, 5, 0, 0, 1, 21, 1, 1, 0,
|
||||||
22, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 26, 1, 0, 0, 0, 25, 27, 3, 4, 2,
|
0, 0, 22, 24, 5, 2, 0, 0, 23, 22, 1, 0, 0, 0, 23, 24, 1, 0, 0, 0, 24, 26,
|
||||||
0, 26, 25, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30,
|
1, 0, 0, 0, 25, 27, 3, 4, 2, 0, 26, 25, 1, 0, 0, 0, 26, 27, 1, 0, 0, 0,
|
||||||
5, 3, 0, 0, 29, 31, 3, 6, 3, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0,
|
27, 28, 1, 0, 0, 0, 28, 30, 5, 2, 0, 0, 29, 31, 3, 6, 3, 0, 30, 29, 1,
|
||||||
31, 33, 1, 0, 0, 0, 32, 34, 5, 3, 0, 0, 33, 32, 1, 0, 0, 0, 33, 34, 1,
|
0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 33, 1, 0, 0, 0, 32, 34, 5, 2, 0, 0, 33,
|
||||||
0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 37, 3, 8, 4, 0, 36, 35, 1, 0, 0, 0, 36,
|
32, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 37, 3, 8, 4,
|
||||||
37, 1, 0, 0, 0, 37, 3, 1, 0, 0, 0, 38, 39, 5, 4, 0, 0, 39, 5, 1, 0, 0,
|
0, 36, 35, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 3, 1, 0, 0, 0, 38, 39, 5,
|
||||||
0, 40, 41, 5, 4, 0, 0, 41, 7, 1, 0, 0, 0, 42, 44, 5, 1, 0, 0, 43, 45, 5,
|
3, 0, 0, 39, 5, 1, 0, 0, 0, 40, 41, 5, 3, 0, 0, 41, 43, 5, 2, 0, 0, 42,
|
||||||
3, 0, 0, 44, 43, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 50, 1, 0, 0, 0, 46,
|
40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 45, 5, 3, 0,
|
||||||
48, 5, 4, 0, 0, 47, 49, 5, 3, 0, 0, 48, 47, 1, 0, 0, 0, 48, 49, 1, 0, 0,
|
0, 45, 7, 1, 0, 0, 0, 46, 48, 5, 1, 0, 0, 47, 49, 5, 2, 0, 0, 48, 47, 1,
|
||||||
0, 49, 51, 1, 0, 0, 0, 50, 46, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 50,
|
0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 54, 1, 0, 0, 0, 50, 52, 5, 3, 0, 0, 51,
|
||||||
1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 9, 1, 0, 0, 0, 11, 12, 16, 18, 23,
|
53, 5, 2, 0, 0, 52, 51, 1, 0, 0, 0, 52, 53, 1, 0, 0, 0, 53, 55, 1, 0, 0,
|
||||||
26, 30, 33, 36, 44, 48, 52,
|
0, 54, 50, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56, 57,
|
||||||
|
1, 0, 0, 0, 57, 9, 1, 0, 0, 0, 12, 12, 16, 18, 23, 26, 30, 33, 36, 42,
|
||||||
|
48, 52, 56,
|
||||||
}
|
}
|
||||||
deserializer := antlr.NewATNDeserializer(nil)
|
deserializer := antlr.NewATNDeserializer(nil)
|
||||||
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
||||||
@ -106,10 +108,9 @@ func NewConfigParser(input antlr.TokenStream) *ConfigParser {
|
|||||||
const (
|
const (
|
||||||
ConfigParserEOF = antlr.TokenEOF
|
ConfigParserEOF = antlr.TokenEOF
|
||||||
ConfigParserHASH = 1
|
ConfigParserHASH = 1
|
||||||
ConfigParserMATCH = 2
|
ConfigParserWHITESPACE = 2
|
||||||
ConfigParserWHITESPACE = 3
|
ConfigParserSTRING = 3
|
||||||
ConfigParserSTRING = 4
|
ConfigParserNEWLINE = 4
|
||||||
ConfigParserNEWLINE = 5
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigParser rules.
|
// ConfigParser rules.
|
||||||
@ -652,7 +653,9 @@ type IValueContext interface {
|
|||||||
GetParser() antlr.Parser
|
GetParser() antlr.Parser
|
||||||
|
|
||||||
// Getter signatures
|
// Getter signatures
|
||||||
STRING() antlr.TerminalNode
|
AllSTRING() []antlr.TerminalNode
|
||||||
|
STRING(i int) antlr.TerminalNode
|
||||||
|
WHITESPACE() antlr.TerminalNode
|
||||||
|
|
||||||
// IsValueContext differentiates from other interfaces.
|
// IsValueContext differentiates from other interfaces.
|
||||||
IsValueContext()
|
IsValueContext()
|
||||||
@ -690,8 +693,16 @@ func NewValueContext(parser antlr.Parser, parent antlr.ParserRuleContext, invoki
|
|||||||
|
|
||||||
func (s *ValueContext) GetParser() antlr.Parser { return s.parser }
|
func (s *ValueContext) GetParser() antlr.Parser { return s.parser }
|
||||||
|
|
||||||
func (s *ValueContext) STRING() antlr.TerminalNode {
|
func (s *ValueContext) AllSTRING() []antlr.TerminalNode {
|
||||||
return s.GetToken(ConfigParserSTRING, 0)
|
return s.GetTokens(ConfigParserSTRING)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ValueContext) STRING(i int) antlr.TerminalNode {
|
||||||
|
return s.GetToken(ConfigParserSTRING, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ValueContext) WHITESPACE() antlr.TerminalNode {
|
||||||
|
return s.GetToken(ConfigParserWHITESPACE, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ValueContext) GetRuleContext() antlr.RuleContext {
|
func (s *ValueContext) GetRuleContext() antlr.RuleContext {
|
||||||
@ -718,6 +729,10 @@ func (p *ConfigParser) Value() (localctx IValueContext) {
|
|||||||
localctx = NewValueContext(p, p.GetParserRuleContext(), p.GetState())
|
localctx = NewValueContext(p, p.GetParserRuleContext(), p.GetState())
|
||||||
p.EnterRule(localctx, 6, ConfigParserRULE_value)
|
p.EnterRule(localctx, 6, ConfigParserRULE_value)
|
||||||
p.EnterOuterAlt(localctx, 1)
|
p.EnterOuterAlt(localctx, 1)
|
||||||
|
p.SetState(42)
|
||||||
|
p.GetErrorHandler().Sync(p)
|
||||||
|
|
||||||
|
if p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 8, p.GetParserRuleContext()) == 1 {
|
||||||
{
|
{
|
||||||
p.SetState(40)
|
p.SetState(40)
|
||||||
p.Match(ConfigParserSTRING)
|
p.Match(ConfigParserSTRING)
|
||||||
@ -726,6 +741,26 @@ func (p *ConfigParser) Value() (localctx IValueContext) {
|
|||||||
goto errorExit
|
goto errorExit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
p.SetState(41)
|
||||||
|
p.Match(ConfigParserWHITESPACE)
|
||||||
|
if p.HasError() {
|
||||||
|
// Recognition error - abort rule
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if p.HasError() { // JIM
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
{
|
||||||
|
p.SetState(44)
|
||||||
|
p.Match(ConfigParserSTRING)
|
||||||
|
if p.HasError() {
|
||||||
|
// Recognition error - abort rule
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
errorExit:
|
errorExit:
|
||||||
if p.HasError() {
|
if p.HasError() {
|
||||||
@ -836,43 +871,9 @@ func (p *ConfigParser) LeadingComment() (localctx ILeadingCommentContext) {
|
|||||||
var _la int
|
var _la int
|
||||||
|
|
||||||
p.EnterOuterAlt(localctx, 1)
|
p.EnterOuterAlt(localctx, 1)
|
||||||
{
|
|
||||||
p.SetState(42)
|
|
||||||
p.Match(ConfigParserHASH)
|
|
||||||
if p.HasError() {
|
|
||||||
// Recognition error - abort rule
|
|
||||||
goto errorExit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.SetState(44)
|
|
||||||
p.GetErrorHandler().Sync(p)
|
|
||||||
if p.HasError() {
|
|
||||||
goto errorExit
|
|
||||||
}
|
|
||||||
_la = p.GetTokenStream().LA(1)
|
|
||||||
|
|
||||||
if _la == ConfigParserWHITESPACE {
|
|
||||||
{
|
|
||||||
p.SetState(43)
|
|
||||||
p.Match(ConfigParserWHITESPACE)
|
|
||||||
if p.HasError() {
|
|
||||||
// Recognition error - abort rule
|
|
||||||
goto errorExit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
p.SetState(50)
|
|
||||||
p.GetErrorHandler().Sync(p)
|
|
||||||
if p.HasError() {
|
|
||||||
goto errorExit
|
|
||||||
}
|
|
||||||
_la = p.GetTokenStream().LA(1)
|
|
||||||
|
|
||||||
for ok := true; ok; ok = _la == ConfigParserSTRING {
|
|
||||||
{
|
{
|
||||||
p.SetState(46)
|
p.SetState(46)
|
||||||
p.Match(ConfigParserSTRING)
|
p.Match(ConfigParserHASH)
|
||||||
if p.HasError() {
|
if p.HasError() {
|
||||||
// Recognition error - abort rule
|
// Recognition error - abort rule
|
||||||
goto errorExit
|
goto errorExit
|
||||||
@ -896,13 +897,47 @@ func (p *ConfigParser) LeadingComment() (localctx ILeadingCommentContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
p.SetState(54)
|
||||||
|
p.GetErrorHandler().Sync(p)
|
||||||
|
if p.HasError() {
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
_la = p.GetTokenStream().LA(1)
|
||||||
|
|
||||||
|
for ok := true; ok; ok = _la == ConfigParserSTRING {
|
||||||
|
{
|
||||||
|
p.SetState(50)
|
||||||
|
p.Match(ConfigParserSTRING)
|
||||||
|
if p.HasError() {
|
||||||
|
// Recognition error - abort rule
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
}
|
||||||
p.SetState(52)
|
p.SetState(52)
|
||||||
p.GetErrorHandler().Sync(p)
|
p.GetErrorHandler().Sync(p)
|
||||||
if p.HasError() {
|
if p.HasError() {
|
||||||
goto errorExit
|
goto errorExit
|
||||||
}
|
}
|
||||||
_la = p.GetTokenStream().LA(1)
|
_la = p.GetTokenStream().LA(1)
|
||||||
|
|
||||||
|
if _la == ConfigParserWHITESPACE {
|
||||||
|
{
|
||||||
|
p.SetState(51)
|
||||||
|
p.Match(ConfigParserWHITESPACE)
|
||||||
|
if p.HasError() {
|
||||||
|
// Recognition error - abort rule
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
p.SetState(56)
|
||||||
|
p.GetErrorHandler().Sync(p)
|
||||||
|
if p.HasError() {
|
||||||
|
goto errorExit
|
||||||
|
}
|
||||||
|
_la = p.GetTokenStream().LA(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
errorExit:
|
errorExit:
|
||||||
|
@ -58,3 +58,321 @@ PasswordAuthentication yes
|
|||||||
t.Errorf("Expected second entry to be PasswordAuthentication yes, but got: %v", secondEntry)
|
t.Errorf("Expected second entry to be PasswordAuthentication yes, but got: %v", secondEntry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatchSimpleBlock(
|
||||||
|
t *testing.T,
|
||||||
|
) {
|
||||||
|
input := utils.Dedent(`
|
||||||
|
PermitRootLogin no
|
||||||
|
|
||||||
|
Match 192.168.0.1
|
||||||
|
PasswordAuthentication yes
|
||||||
|
`)
|
||||||
|
p := NewSSHConfig()
|
||||||
|
errors := p.Parse(input)
|
||||||
|
|
||||||
|
if len(errors) != 0 {
|
||||||
|
t.Fatalf("Expected no errors, got %v", errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(p.Options.Size() == 2 &&
|
||||||
|
len(utils.KeysOfMap(p.CommentLines)) == 0) {
|
||||||
|
t.Errorf("Expected 1 option and no comment lines, but got: %v, %v", p.Options, p.CommentLines)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawFirstEntry, _ := p.Options.Get(uint32(0))
|
||||||
|
firstEntry := rawFirstEntry.(*SSHOption)
|
||||||
|
if !(firstEntry.Value == "PermitRootLogin no") {
|
||||||
|
t.Errorf("Expected first entry to be 'PermitRootLogin no', but got: %v", firstEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawSecondEntry, _ := p.Options.Get(uint32(2))
|
||||||
|
secondEntry := rawSecondEntry.(*SSHMatchBlock)
|
||||||
|
if !(secondEntry.MatchEntry.Value == "Match 192.168.0.1") {
|
||||||
|
t.Errorf("Expected second entry to be 'Match 192.168.0.1', but got: %v", secondEntry.MatchEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(secondEntry.Options.Size() == 1) {
|
||||||
|
t.Errorf("Expected 1 option in match block, but got: %v", secondEntry.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawThirdEntry, _ := secondEntry.Options.Get(uint32(3))
|
||||||
|
thirdEntry := rawThirdEntry.(*SSHOption)
|
||||||
|
if !(thirdEntry.Key.Value == "PasswordAuthentication" && thirdEntry.OptionValue.Value == "yes") {
|
||||||
|
t.Errorf("Expected third entry to be 'PasswordAuthentication yes', but got: %v", thirdEntry.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultipleMatchBlocks(
|
||||||
|
t *testing.T,
|
||||||
|
) {
|
||||||
|
input := utils.Dedent(`
|
||||||
|
PermitRootLogin no
|
||||||
|
|
||||||
|
Match 192.168.0.1
|
||||||
|
PasswordAuthentication yes
|
||||||
|
AllowUsers root user
|
||||||
|
|
||||||
|
Match 192.168.0.2
|
||||||
|
MaxAuthTries 3
|
||||||
|
`)
|
||||||
|
p := NewSSHConfig()
|
||||||
|
errors := p.Parse(input)
|
||||||
|
|
||||||
|
if len(errors) != 0 {
|
||||||
|
t.Fatalf("Expected no errors, got %v", errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(p.Options.Size() == 3 &&
|
||||||
|
len(utils.KeysOfMap(p.CommentLines)) == 0) {
|
||||||
|
t.Errorf("Expected 3 options and no comment lines, but got: %v, %v", p.Options, p.CommentLines)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawSecondEntry, _ := p.Options.Get(uint32(2))
|
||||||
|
secondEntry := rawSecondEntry.(*SSHMatchBlock)
|
||||||
|
if !(secondEntry.Options.Size() == 2) {
|
||||||
|
t.Errorf("Expected 2 options in second match block, but got: %v", secondEntry.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawThirdEntry, _ := secondEntry.Options.Get(uint32(3))
|
||||||
|
thirdEntry := rawThirdEntry.(*SSHOption)
|
||||||
|
if !(thirdEntry.Key.Value == "PasswordAuthentication" && thirdEntry.OptionValue.Value == "yes") {
|
||||||
|
t.Errorf("Expected third entry to be 'PasswordAuthentication yes', but got: %v", thirdEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawFourthEntry, _ := secondEntry.Options.Get(uint32(4))
|
||||||
|
fourthEntry := rawFourthEntry.(*SSHOption)
|
||||||
|
if !(fourthEntry.Key.Value == "AllowUsers" && fourthEntry.OptionValue.Value == "root user") {
|
||||||
|
t.Errorf("Expected fourth entry to be 'AllowUsers root user', but got: %v", fourthEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawFifthEntry, _ := p.Options.Get(uint32(6))
|
||||||
|
fifthEntry := rawFifthEntry.(*SSHMatchBlock)
|
||||||
|
if !(fifthEntry.Options.Size() == 1) {
|
||||||
|
t.Errorf("Expected 1 option in fifth match block, but got: %v", fifthEntry.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawSixthEntry, _ := fifthEntry.Options.Get(uint32(7))
|
||||||
|
sixthEntry := rawSixthEntry.(*SSHOption)
|
||||||
|
if !(sixthEntry.Key.Value == "MaxAuthTries" && sixthEntry.OptionValue.Value == "3") {
|
||||||
|
t.Errorf("Expected sixth entry to be 'MaxAuthTries 3', but got: %v", sixthEntry.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestComplexExample(
|
||||||
|
t *testing.T,
|
||||||
|
) {
|
||||||
|
// From https://gist.github.com/kjellski/5940875
|
||||||
|
input := utils.Dedent(`
|
||||||
|
# This is the sshd server system-wide configuration file. See
|
||||||
|
# sshd_config(5) for more information.
|
||||||
|
|
||||||
|
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
||||||
|
|
||||||
|
# The strategy used for options in the default sshd_config shipped with
|
||||||
|
# OpenSSH is to specify options with their default value where
|
||||||
|
# possible, but leave them commented. Uncommented options change a
|
||||||
|
# default value.
|
||||||
|
|
||||||
|
#Port 22
|
||||||
|
#AddressFamily any
|
||||||
|
#ListenAddress 0.0.0.0
|
||||||
|
#ListenAddress ::
|
||||||
|
|
||||||
|
# The default requires explicit activation of protocol 1
|
||||||
|
#Protocol 2
|
||||||
|
|
||||||
|
# HostKey for protocol version 1
|
||||||
|
#HostKey /etc/ssh/ssh_host_key
|
||||||
|
# HostKeys for protocol version 2
|
||||||
|
#HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
#HostKey /etc/ssh/ssh_host_dsa_key
|
||||||
|
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||||
|
|
||||||
|
# Lifetime and size of ephemeral version 1 server key
|
||||||
|
#KeyRegenerationInterval 1h
|
||||||
|
#ServerKeyBits 1024
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
# obsoletes QuietMode and FascistLogging
|
||||||
|
#SyslogFacility AUTH
|
||||||
|
#LogLevel INFO
|
||||||
|
|
||||||
|
# Authentication:
|
||||||
|
|
||||||
|
#LoginGraceTime 2m
|
||||||
|
#BC# Root only allowed to login from LAN IP ranges listed at end
|
||||||
|
PermitRootLogin no
|
||||||
|
#PermitRootLogin yes
|
||||||
|
#StrictModes yes
|
||||||
|
#MaxAuthTries 6
|
||||||
|
#MaxSessions 10
|
||||||
|
|
||||||
|
#RSAAuthentication yes
|
||||||
|
#PubkeyAuthentication yes
|
||||||
|
#AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
|
||||||
|
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
||||||
|
#RhostsRSAAuthentication no
|
||||||
|
# similar for protocol version 2
|
||||||
|
#HostbasedAuthentication no
|
||||||
|
# Change to yes if you don't trust ~/.ssh/known_hosts for
|
||||||
|
# RhostsRSAAuthentication and HostbasedAuthentication
|
||||||
|
#IgnoreUserKnownHosts no
|
||||||
|
# Don't read the user's ~/.rhosts and ~/.shosts files
|
||||||
|
#IgnoreRhosts yes
|
||||||
|
|
||||||
|
# To disable tunneled clear text passwords, change to no here!
|
||||||
|
#BC# Disable password authentication by default (except for LAN IP ranges listed later)
|
||||||
|
PasswordAuthentication no
|
||||||
|
PermitEmptyPasswords no
|
||||||
|
#BC# Have to allow root here because AllowUsers not allowed in Match block. It will not work though because of PermitRootLogin.
|
||||||
|
#BC# This is no longer true as of 6.1. AllowUsers is now allowed in a Match block.
|
||||||
|
AllowUsers kmk root
|
||||||
|
|
||||||
|
# Change to no to disable s/key passwords
|
||||||
|
#BC# I occasionally use s/key one time passwords generated by a phone app
|
||||||
|
ChallengeResponseAuthentication yes
|
||||||
|
|
||||||
|
# Kerberos options
|
||||||
|
#KerberosAuthentication no
|
||||||
|
#KerberosOrLocalPasswd yes
|
||||||
|
#KerberosTicketCleanup yes
|
||||||
|
#KerberosGetAFSToken no
|
||||||
|
|
||||||
|
# GSSAPI options
|
||||||
|
#GSSAPIAuthentication no
|
||||||
|
#GSSAPICleanupCredentials yes
|
||||||
|
|
||||||
|
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||||
|
# and session processing. If this is enabled, PAM authentication will
|
||||||
|
# be allowed through the ChallengeResponseAuthentication and
|
||||||
|
# PasswordAuthentication. Depending on your PAM configuration,
|
||||||
|
# PAM authentication via ChallengeResponseAuthentication may bypass
|
||||||
|
# the setting of "PermitRootLogin without-password".
|
||||||
|
# If you just want the PAM account and session checks to run without
|
||||||
|
# PAM authentication, then enable this but set PasswordAuthentication
|
||||||
|
# and ChallengeResponseAuthentication to 'no'.
|
||||||
|
#BC# I would turn this off but I compiled ssh without PAM support so it errors if I set this.
|
||||||
|
#UsePAM no
|
||||||
|
|
||||||
|
#AllowAgentForwarding yes
|
||||||
|
#AllowTcpForwarding yes
|
||||||
|
#GatewayPorts no
|
||||||
|
X11Forwarding yes
|
||||||
|
#X11DisplayOffset 10
|
||||||
|
#X11UseLocalhost yes
|
||||||
|
#PrintMotd yes
|
||||||
|
#PrintLastLog yes
|
||||||
|
#TCPKeepAlive yes
|
||||||
|
#UseLogin no
|
||||||
|
#UsePrivilegeSeparation yes
|
||||||
|
#PermitUserEnvironment no
|
||||||
|
#Compression delayed
|
||||||
|
#ClientAliveInterval 0
|
||||||
|
#ClientAliveCountMax 3
|
||||||
|
#UseDNS yes
|
||||||
|
#PidFile /var/run/sshd.pid
|
||||||
|
#MaxStartups 10
|
||||||
|
#PermitTunnel no
|
||||||
|
#ChrootDirectory none
|
||||||
|
|
||||||
|
# no default banner path
|
||||||
|
#Banner none
|
||||||
|
|
||||||
|
# override default of no subsystems
|
||||||
|
#Subsystem sftp /usr/lib/misc/sftp-server
|
||||||
|
Subsystem sftp internal-sftp
|
||||||
|
|
||||||
|
# the following are HPN related configuration options
|
||||||
|
# tcp receive buffer polling. disable in non autotuning kernels
|
||||||
|
#TcpRcvBufPoll yes
|
||||||
|
|
||||||
|
# allow the use of the none cipher
|
||||||
|
#NoneEnabled no
|
||||||
|
|
||||||
|
# disable hpn performance boosts.
|
||||||
|
#HPNDisabled no
|
||||||
|
|
||||||
|
# buffer size for hpn to non-hpn connections
|
||||||
|
#HPNBufferSize 2048
|
||||||
|
|
||||||
|
|
||||||
|
# Example of overriding settings on a per-user basis
|
||||||
|
Match User anoncvs
|
||||||
|
X11Forwarding no
|
||||||
|
AllowTcpForwarding no
|
||||||
|
ForceCommand cvs server
|
||||||
|
|
||||||
|
#BC# My internal networks
|
||||||
|
#BC# Root can log in from here but only with a key and kmk can log in here with a password.
|
||||||
|
Match Address 172.22.100.0/24,172.22.5.0/24,127.0.0.1
|
||||||
|
PermitRootLogin without-password
|
||||||
|
PasswordAuthentication yes
|
||||||
|
`)
|
||||||
|
p := NewSSHConfig()
|
||||||
|
errors := p.Parse(input)
|
||||||
|
|
||||||
|
if len(errors) != 0 {
|
||||||
|
t.Fatalf("Expected no errors, got %v", errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(p.Options.Size() == 9 &&
|
||||||
|
len(utils.KeysOfMap(p.CommentLines)) == 105) {
|
||||||
|
t.Errorf("Expected 9 options and 105 comment lines, but got: %v, %v", p.Options, p.CommentLines)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawFirstEntry, _ := p.Options.Get(uint32(38))
|
||||||
|
firstEntry := rawFirstEntry.(*SSHOption)
|
||||||
|
if !(firstEntry.Key.Value == "PermitRootLogin" && firstEntry.OptionValue.Value == "no") {
|
||||||
|
t.Errorf("Expected first entry to be 'PermitRootLogin no', but got: %v", firstEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawSecondEntry, _ := p.Options.Get(uint32(60))
|
||||||
|
secondEntry := rawSecondEntry.(*SSHOption)
|
||||||
|
if !(secondEntry.Key.Value == "PasswordAuthentication" && secondEntry.OptionValue.Value == "no") {
|
||||||
|
t.Errorf("Expected second entry to be 'PasswordAuthentication no', but got: %v", secondEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawThirdEntry, _ := p.Options.Get(uint32(118))
|
||||||
|
thirdEntry := rawThirdEntry.(*SSHOption)
|
||||||
|
if !(thirdEntry.Key.Value == "Subsystem" && thirdEntry.OptionValue.Value == "sftp\tinternal-sftp") {
|
||||||
|
t.Errorf("Expected third entry to be 'Subsystem sftp internal-sftp', but got: %v", thirdEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawFourthEntry, _ := p.Options.Get(uint32(135))
|
||||||
|
fourthEntry := rawFourthEntry.(*SSHMatchBlock)
|
||||||
|
if !(fourthEntry.MatchEntry.Value == "Match User anoncvs") {
|
||||||
|
t.Errorf("Expected fourth entry to be 'Match User anoncvs', but got: %v", fourthEntry.MatchEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(fourthEntry.Options.Size() == 3) {
|
||||||
|
t.Errorf("Expected 3 options in fourth match block, but got: %v", fourthEntry.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawFifthEntry, _ := fourthEntry.Options.Get(uint32(136))
|
||||||
|
fifthEntry := rawFifthEntry.(*SSHOption)
|
||||||
|
if !(fifthEntry.Key.Value == "X11Forwarding" && fifthEntry.OptionValue.Value == "no") {
|
||||||
|
t.Errorf("Expected fifth entry to be 'X11Forwarding no', but got: %v", fifthEntry.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawSixthEntry, _ := p.Options.Get(uint32(142))
|
||||||
|
sixthEntry := rawSixthEntry.(*SSHMatchBlock)
|
||||||
|
if !(sixthEntry.MatchEntry.Value == "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)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(sixthEntry.MatchEntry.Key.Value == "Match" && sixthEntry.MatchEntry.OptionValue.Value == "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)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(sixthEntry.Options.Size() == 2) {
|
||||||
|
t.Errorf("Expected 2 options in sixth match block, but got: %v", sixthEntry.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawSeventhEntry, _ := sixthEntry.Options.Get(uint32(143))
|
||||||
|
seventhEntry := rawSeventhEntry.(*SSHOption)
|
||||||
|
if !(seventhEntry.Key.Value == "PermitRootLogin" && seventhEntry.OptionValue.Value == "without-password") {
|
||||||
|
t.Errorf("Expected seventh entry to be 'PermitRootLogin without-password', but got: %v", seventhEntry.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user