nuclei/v2/internal/runner/options.go

151 lines
3.9 KiB
Go
Raw Normal View History

2020-04-03 22:15:39 +00:00
package runner
import (
"bufio"
2020-08-29 13:26:11 +00:00
"errors"
"net/url"
2020-04-03 22:15:39 +00:00
"os"
"strings"
2020-04-03 22:15:39 +00:00
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/formatter"
"github.com/projectdiscovery/gologger/levels"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolinit"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
2020-04-03 22:15:39 +00:00
)
// ParseOptions parses the command line flags provided by a user
func ParseOptions(options *types.Options) {
err := protocolinit.Init(options)
if err != nil {
gologger.Fatal().Msgf("Could not initialize protocols: %s\n", err)
}
2020-04-03 22:15:39 +00:00
// Check if stdin pipe was given
options.Stdin = hasStdin()
// Read the inputs and configure the logging
configureOutput(options)
2020-04-03 22:15:39 +00:00
// Show the user the banner
showBanner()
if options.Version {
gologger.Info().Msgf("Current Version: %s\n", Version)
2020-04-03 22:15:39 +00:00
os.Exit(0)
}
if options.TemplatesVersion {
config, err := readConfiguration()
if err != nil {
gologger.Fatal().Msgf("Could not read template configuration: %s\n", err)
}
gologger.Info().Msgf("Current nuclei-templates version: %s (%s)\n", config.CurrentVersion, config.TemplatesDirectory)
os.Exit(0)
}
2020-04-03 22:15:39 +00:00
// Validate the options passed by the user and if any
// invalid options have been used, exit.
if err = validateOptions(options); err != nil {
gologger.Fatal().Msgf("Program exiting: %s\n", err)
2020-04-03 22:15:39 +00:00
}
// Load the resolvers if user asked for them
loadResolvers(options)
2020-04-03 22:15:39 +00:00
}
// hasStdin returns true if we have stdin input
2020-04-03 22:15:39 +00:00
func hasStdin() bool {
2020-09-28 10:50:00 +00:00
stat, err := os.Stdin.Stat()
2020-04-03 22:15:39 +00:00
if err != nil {
return false
}
2020-09-28 10:50:00 +00:00
isPipedFromChrDev := (stat.Mode() & os.ModeCharDevice) == 0
isPipedFromFIFO := (stat.Mode() & os.ModeNamedPipe) != 0
2020-09-28 10:50:00 +00:00
return isPipedFromChrDev || isPipedFromFIFO
2020-04-03 22:15:39 +00:00
}
2020-08-29 13:26:11 +00:00
// validateOptions validates the configuration options passed
func validateOptions(options *types.Options) error {
2020-08-29 13:26:11 +00:00
// Both verbose and silent flags were used
if options.Verbose && options.Silent {
return errors.New("both verbose and silent mode specified")
}
if !options.TemplateList {
2020-08-29 13:26:11 +00:00
// Check if a list of templates was provided and it exists
if len(options.Templates) == 0 && len(options.Tags) == 0 && !options.UpdateTemplates {
2020-08-29 13:26:11 +00:00
return errors.New("no template/templates provided")
}
}
// Validate proxy options if provided
err := validateProxyURL(options.ProxyURL, "invalid http proxy format (It should be http://username:password@host:port)")
2020-08-29 14:25:30 +00:00
if err != nil {
return err
}
err = validateProxyURL(options.ProxySocksURL, "invalid socks proxy format (It should be socks5://username:password@host:port)")
2020-08-29 14:25:30 +00:00
if err != nil {
return err
2020-08-29 13:26:11 +00:00
}
2020-08-29 14:25:30 +00:00
return nil
}
func validateProxyURL(proxyURL, message string) error {
if proxyURL != "" && !isValidURL(proxyURL) {
return errors.New(message)
2020-08-29 13:26:11 +00:00
}
return nil
}
2020-08-29 14:25:30 +00:00
func isValidURL(urlString string) bool {
_, err := url.Parse(urlString)
2020-08-29 13:26:11 +00:00
return err == nil
}
// configureOutput configures the output on the screen
func configureOutput(options *types.Options) {
2020-08-29 13:26:11 +00:00
// If the user desires verbose output, show verbose output
if options.Verbose {
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
}
if options.Debug {
gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug)
2020-08-29 13:26:11 +00:00
}
if options.NoColor {
gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true))
2020-08-29 13:26:11 +00:00
}
if options.Silent {
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
2020-08-29 13:26:11 +00:00
}
}
// loadResolvers loads resolvers from both user provided flag and file
func loadResolvers(options *types.Options) {
if options.ResolversFile == "" {
return
}
file, err := os.Open(options.ResolversFile)
if err != nil {
gologger.Fatal().Msgf("Could not open resolvers file: %s\n", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
part := scanner.Text()
if part == "" {
continue
}
if strings.Contains(part, ":") {
options.InternalResolversList = append(options.InternalResolversList, part)
} else {
options.InternalResolversList = append(options.InternalResolversList, part+":53")
}
}
}