diff --git a/handlers/sshd_config/analyzer/options.go b/handlers/sshd_config/analyzer/options.go index 58132b3..13140f0 100644 --- a/handlers/sshd_config/analyzer/options.go +++ b/handlers/sshd_config/analyzer/options.go @@ -18,42 +18,100 @@ func analyzeOptionsAreValid( it := d.Config.Options.Iterator() for it.Next() { - line := it.Key().(uint32) entry := it.Value().(ast.SSHEntry) - option := entry.GetOption() - - if option.Key != nil { - docOption, found := fields.Options[option.Key.Value] - - if !found { - errs = append(errs, common.LSPError{ - Range: option.Key.LocationRange, - Err: errors.New(fmt.Sprintf("Unknown option: %s", option.Key.Value)), - }) - continue - } - - if option.OptionValue == nil { - continue - } - - invalidValues := docOption.CheckIsValid(option.OptionValue.Value) - - errs = append( - errs, - utils.Map( - invalidValues, - func(invalidValue *docvalues.InvalidValue) common.LSPError { - err := docvalues.LSPErrorFromInvalidValue(line, *invalidValue) - err.ShiftCharacter(option.OptionValue.Start.Character) - - return err - }, - )..., - ) - + switch entry.(type) { + case *ast.SSHOption: + errs = append(errs, checkOption(entry.(*ast.SSHOption), false)...) + case *ast.SSHMatchBlock: + matchBlock := entry.(*ast.SSHMatchBlock) + errs = append(errs, checkMatchBlock(matchBlock)...) } + + } + + return errs +} + +func checkOption( + option *ast.SSHOption, + isInMatchBlock bool, +) []common.LSPError { + errs := make([]common.LSPError, 0) + + if option.Key != nil { + docOption, found := fields.Options[option.Key.Value] + + if !found { + errs = append(errs, common.LSPError{ + Range: option.Key.LocationRange, + Err: errors.New(fmt.Sprintf("Unknown option: %s", option.Key.Value)), + }) + + return errs + } + + if _, found := fields.MatchAllowedOptions[option.Key.Value]; !found && isInMatchBlock { + errs = append(errs, common.LSPError{ + Range: option.Key.LocationRange, + Err: errors.New(fmt.Sprintf("Option '%s' is not allowed inside Match blocks", option.Key.Value)), + }) + + return errs + } + + if option.OptionValue == nil { + return errs + } + + invalidValues := docOption.CheckIsValid(option.OptionValue.Value) + + errs = append( + errs, + utils.Map( + invalidValues, + func(invalidValue *docvalues.InvalidValue) common.LSPError { + err := docvalues.LSPErrorFromInvalidValue(option.Start.Line, *invalidValue) + err.ShiftCharacter(option.OptionValue.Start.Character) + + return err + }, + )..., + ) + } + + return errs +} + +func checkMatchBlock( + matchBlock *ast.SSHMatchBlock, +) []common.LSPError { + errs := make([]common.LSPError, 0) + + matchOption := matchBlock.MatchEntry.OptionValue + if matchOption != nil { + invalidValues := fields.Options["Match"].CheckIsValid(matchOption.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() { + option := it.Value().(*ast.SSHOption) + + errs = append(errs, checkOption(option, true)...) } return errs diff --git a/handlers/sshd_config/fields/fields.go b/handlers/sshd_config/fields/fields.go index 4de4c20..41a233c 100644 --- a/handlers/sshd_config/fields/fields.go +++ b/handlers/sshd_config/fields/fields.go @@ -574,8 +574,8 @@ Only a subset of keywords may be used on the lines following a Match keyword. Av SubValue: docvalues.KeyEnumAssignmentValue{ Separator: " ", Values: map[docvalues.EnumString]docvalues.Value{ - docvalues.CreateEnumString("User"): docvalues.UserValue("", true), - docvalues.CreateEnumString("Group"): docvalues.GroupValue("", true), + docvalues.CreateEnumString("User"): docvalues.StringValue{}, + docvalues.CreateEnumString("Group"): docvalues.StringValue{}, docvalues.CreateEnumString("Host"): docvalues.StringValue{}, docvalues.CreateEnumString("LocalAddress"): docvalues.StringValue{}, docvalues.CreateEnumString("LocalPort"): docvalues.NumberValue{Min: &ZERO, Max: &MAX_PORT}, diff --git a/handlers/sshd_config/lsp/text-document-hover.go b/handlers/sshd_config/lsp/text-document-hover.go index 61d19cd..bb73a41 100644 --- a/handlers/sshd_config/lsp/text-document-hover.go +++ b/handlers/sshd_config/lsp/text-document-hover.go @@ -9,5 +9,12 @@ func TextDocumentHover( context *glsp.Context, params *protocol.HoverParams, ) (*protocol.Hover, error) { + // line := params.Position.Line + // cursor := params.Position.Character + // + // d := sshdconfig.DocumentParserMap[params.TextDocument.URI] + // + // entry, matchBlock := d.Config.FindOption(line) + return nil, nil }