1283 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1283 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package config
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"runtime"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	syslog "github.com/RackSec/srslog"
 | 
						|
	valid "github.com/asaskevich/govalidator"
 | 
						|
	log "github.com/sirupsen/logrus"
 | 
						|
	"golang.org/x/xerrors"
 | 
						|
)
 | 
						|
 | 
						|
// Version of Vuls
 | 
						|
var Version = "`make build` or `make install` will show the version"
 | 
						|
 | 
						|
// Revision of Git
 | 
						|
var Revision string
 | 
						|
 | 
						|
// Conf has Configuration
 | 
						|
var Conf Config
 | 
						|
 | 
						|
const (
 | 
						|
	// RedHat is
 | 
						|
	RedHat = "redhat"
 | 
						|
 | 
						|
	// Debian is
 | 
						|
	Debian = "debian"
 | 
						|
 | 
						|
	// Ubuntu is
 | 
						|
	Ubuntu = "ubuntu"
 | 
						|
 | 
						|
	// CentOS is
 | 
						|
	CentOS = "centos"
 | 
						|
 | 
						|
	// Fedora is
 | 
						|
	Fedora = "fedora"
 | 
						|
 | 
						|
	// Amazon is
 | 
						|
	Amazon = "amazon"
 | 
						|
 | 
						|
	// Oracle is
 | 
						|
	Oracle = "oracle"
 | 
						|
 | 
						|
	// FreeBSD is
 | 
						|
	FreeBSD = "freebsd"
 | 
						|
 | 
						|
	// Raspbian is
 | 
						|
	Raspbian = "raspbian"
 | 
						|
 | 
						|
	// Windows is
 | 
						|
	Windows = "windows"
 | 
						|
 | 
						|
	// OpenSUSE is
 | 
						|
	OpenSUSE = "opensuse"
 | 
						|
 | 
						|
	// OpenSUSELeap is
 | 
						|
	OpenSUSELeap = "opensuse.leap"
 | 
						|
 | 
						|
	// SUSEEnterpriseServer is
 | 
						|
	SUSEEnterpriseServer = "suse.linux.enterprise.server"
 | 
						|
 | 
						|
	// SUSEEnterpriseDesktop is
 | 
						|
	SUSEEnterpriseDesktop = "suse.linux.enterprise.desktop"
 | 
						|
 | 
						|
	// SUSEOpenstackCloud is
 | 
						|
	SUSEOpenstackCloud = "suse.openstack.cloud"
 | 
						|
 | 
						|
	// Alpine is
 | 
						|
	Alpine = "alpine"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// ServerTypePseudo is used for ServerInfo.Type
 | 
						|
	ServerTypePseudo = "pseudo"
 | 
						|
)
 | 
						|
 | 
						|
//Config is struct of Configuration
 | 
						|
type Config struct {
 | 
						|
	Debug      bool   `json:"debug,omitempty"`
 | 
						|
	DebugSQL   bool   `json:"debugSQL,omitempty"`
 | 
						|
	Lang       string `json:"lang,omitempty"`
 | 
						|
	HTTPProxy  string `valid:"url" json:"httpProxy,omitempty"`
 | 
						|
	LogDir     string `json:"logDir,omitempty"`
 | 
						|
	ResultsDir string `json:"resultsDir,omitempty"`
 | 
						|
	Pipe       bool   `json:"pipe,omitempty"`
 | 
						|
	Quiet      bool   `json:"quiet,omitempty"`
 | 
						|
	NoProgress bool   `json:"noProgress,omitempty"`
 | 
						|
 | 
						|
	Default       ServerInfo            `json:"default,omitempty"`
 | 
						|
	Servers       map[string]ServerInfo `json:"servers,omitempty"`
 | 
						|
	CvssScoreOver float64               `json:"cvssScoreOver,omitempty"`
 | 
						|
 | 
						|
	IgnoreUnscoredCves    bool `json:"ignoreUnscoredCves,omitempty"`
 | 
						|
	IgnoreUnfixed         bool `json:"ignoreUnfixed,omitempty"`
 | 
						|
	IgnoreGitHubDismissed bool `json:"ignore_git_hub_dismissed,omitempty"`
 | 
						|
 | 
						|
	SSHNative bool `json:"sshNative,omitempty"`
 | 
						|
	SSHConfig bool `json:"sshConfig,omitempty"`
 | 
						|
 | 
						|
	ContainersOnly bool `json:"containersOnly,omitempty"`
 | 
						|
	LibsOnly       bool `json:"libsOnly,omitempty"`
 | 
						|
	WordPressOnly  bool `json:"wordpressOnly,omitempty"`
 | 
						|
 | 
						|
	CacheDBPath     string `json:"cacheDBPath,omitempty"`
 | 
						|
	TrivyCacheDBDir string `json:"trivyCacheDBDir,omitempty"`
 | 
						|
 | 
						|
	SkipBroken bool `json:"skipBroken,omitempty"`
 | 
						|
	Vvv        bool `json:"vvv,omitempty"`
 | 
						|
	UUID       bool `json:"uuid,omitempty"`
 | 
						|
	DetectIPS  bool `json:"detectIps,omitempty"`
 | 
						|
 | 
						|
	CveDict    GoCveDictConf  `json:"cveDict,omitempty"`
 | 
						|
	OvalDict   GovalDictConf  `json:"ovalDict,omitempty"`
 | 
						|
	Gost       GostConf       `json:"gost,omitempty"`
 | 
						|
	Exploit    ExploitConf    `json:"exploit,omitempty"`
 | 
						|
	Metasploit MetasploitConf `json:"metasploit,omitempty"`
 | 
						|
 | 
						|
	Slack    SlackConf    `json:"-"`
 | 
						|
	EMail    SMTPConf     `json:"-"`
 | 
						|
	HTTP     HTTPConf     `json:"-"`
 | 
						|
	Syslog   SyslogConf   `json:"-"`
 | 
						|
	AWS      AWS          `json:"-"`
 | 
						|
	Azure    Azure        `json:"-"`
 | 
						|
	Stride   StrideConf   `json:"-"`
 | 
						|
	HipChat  HipChatConf  `json:"-"`
 | 
						|
	ChatWork ChatWorkConf `json:"-"`
 | 
						|
	Telegram TelegramConf `json:"-"`
 | 
						|
	Saas     SaasConf     `json:"-"`
 | 
						|
 | 
						|
	RefreshCve        bool `json:"refreshCve,omitempty"`
 | 
						|
	ToSlack           bool `json:"toSlack,omitempty"`
 | 
						|
	ToStride          bool `json:"toStride,omitempty"`
 | 
						|
	ToHipChat         bool `json:"toHipChat,omitempty"`
 | 
						|
	ToChatWork        bool `json:"toChatWork,omitempty"`
 | 
						|
	ToTelegram        bool `json:"ToTelegram,omitempty"`
 | 
						|
	ToEmail           bool `json:"toEmail,omitempty"`
 | 
						|
	ToSyslog          bool `json:"toSyslog,omitempty"`
 | 
						|
	ToLocalFile       bool `json:"toLocalFile,omitempty"`
 | 
						|
	ToS3              bool `json:"toS3,omitempty"`
 | 
						|
	ToAzureBlob       bool `json:"toAzureBlob,omitempty"`
 | 
						|
	ToSaas            bool `json:"toSaas,omitempty"`
 | 
						|
	ToHTTP            bool `json:"toHTTP,omitempty"`
 | 
						|
	FormatXML         bool `json:"formatXML,omitempty"`
 | 
						|
	FormatJSON        bool `json:"formatJSON,omitempty"`
 | 
						|
	FormatOneEMail    bool `json:"formatOneEMail,omitempty"`
 | 
						|
	FormatOneLineText bool `json:"formatOneLineText,omitempty"`
 | 
						|
	FormatList        bool `json:"formatList,omitempty"`
 | 
						|
	FormatFullText    bool `json:"formatFullText,omitempty"`
 | 
						|
	GZIP              bool `json:"gzip,omitempty"`
 | 
						|
	Diff              bool `json:"diff,omitempty"`
 | 
						|
	WpIgnoreInactive  bool `json:"wpIgnoreInactive,omitempty"`
 | 
						|
}
 | 
						|
 | 
						|
// ValidateOnConfigtest validates
 | 
						|
func (c Config) ValidateOnConfigtest() bool {
 | 
						|
	errs := c.checkSSHKeyExist()
 | 
						|
 | 
						|
	if runtime.GOOS == "windows" && !c.SSHNative {
 | 
						|
		errs = append(errs, xerrors.New("-ssh-native-insecure is needed on windows"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, err := range errs {
 | 
						|
		log.Error(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return len(errs) == 0
 | 
						|
}
 | 
						|
 | 
						|
// ValidateOnScan validates configuration
 | 
						|
func (c Config) ValidateOnScan() bool {
 | 
						|
	errs := c.checkSSHKeyExist()
 | 
						|
 | 
						|
	if runtime.GOOS == "windows" && !c.SSHNative {
 | 
						|
		errs = append(errs, xerrors.New("-ssh-native-insecure is needed on windows"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.ResultsDir) != 0 {
 | 
						|
		if ok, _ := valid.IsFilePath(c.ResultsDir); !ok {
 | 
						|
			errs = append(errs, xerrors.Errorf(
 | 
						|
				"JSON base directory must be a *Absolute* file path. -results-dir: %s", c.ResultsDir))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.CacheDBPath) != 0 {
 | 
						|
		if ok, _ := valid.IsFilePath(c.CacheDBPath); !ok {
 | 
						|
			errs = append(errs, xerrors.Errorf(
 | 
						|
				"Cache DB path must be a *Absolute* file path. -cache-dbpath: %s",
 | 
						|
				c.CacheDBPath))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, err := range errs {
 | 
						|
		log.Error(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return len(errs) == 0
 | 
						|
}
 | 
						|
 | 
						|
func (c Config) checkSSHKeyExist() (errs []error) {
 | 
						|
	for serverName, v := range c.Servers {
 | 
						|
		if v.Type == ServerTypePseudo {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if v.KeyPath != "" {
 | 
						|
			if _, err := os.Stat(v.KeyPath); err != nil {
 | 
						|
				errs = append(errs, xerrors.Errorf(
 | 
						|
					"%s is invalid. keypath: %s not exists", serverName, v.KeyPath))
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return errs
 | 
						|
}
 | 
						|
 | 
						|
// ValidateOnReportDB validates configuration
 | 
						|
func (c Config) ValidateOnReportDB() bool {
 | 
						|
	errs := []error{}
 | 
						|
 | 
						|
	if err := validateDB("cvedb", c.CveDict.Type, c.CveDict.SQLite3Path, c.CveDict.URL); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := validateDB("ovaldb", c.OvalDict.Type, c.OvalDict.SQLite3Path, c.OvalDict.URL); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := validateDB("gostdb", c.Gost.Type, c.Gost.SQLite3Path, c.Gost.URL); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := validateDB("exploitdb", c.Exploit.Type, c.Exploit.SQLite3Path, c.Exploit.URL); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if err := validateDB("msfdb", c.Metasploit.Type, c.Metasploit.SQLite3Path, c.Metasploit.URL); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, err := range errs {
 | 
						|
		log.Error(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return len(errs) == 0
 | 
						|
}
 | 
						|
 | 
						|
// ValidateOnReport validates configuration
 | 
						|
func (c Config) ValidateOnReport() bool {
 | 
						|
	errs := []error{}
 | 
						|
 | 
						|
	if len(c.ResultsDir) != 0 {
 | 
						|
		if ok, _ := valid.IsFilePath(c.ResultsDir); !ok {
 | 
						|
			errs = append(errs, xerrors.Errorf(
 | 
						|
				"JSON base directory must be a *Absolute* file path. -results-dir: %s", c.ResultsDir))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if mailerrs := c.EMail.Validate(); 0 < len(mailerrs) {
 | 
						|
		errs = append(errs, mailerrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if slackerrs := c.Slack.Validate(); 0 < len(slackerrs) {
 | 
						|
		errs = append(errs, slackerrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if hipchaterrs := c.HipChat.Validate(); 0 < len(hipchaterrs) {
 | 
						|
		errs = append(errs, hipchaterrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if chatworkerrs := c.ChatWork.Validate(); 0 < len(chatworkerrs) {
 | 
						|
		errs = append(errs, chatworkerrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if strideerrs := c.Stride.Validate(); 0 < len(strideerrs) {
 | 
						|
		errs = append(errs, strideerrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if telegramerrs := c.Telegram.Validate(); 0 < len(telegramerrs) {
 | 
						|
		errs = append(errs, telegramerrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if saaserrs := c.Saas.Validate(); 0 < len(saaserrs) {
 | 
						|
		errs = append(errs, saaserrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if syslogerrs := c.Syslog.Validate(); 0 < len(syslogerrs) {
 | 
						|
		errs = append(errs, syslogerrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if httperrs := c.HTTP.Validate(); 0 < len(httperrs) {
 | 
						|
		errs = append(errs, httperrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, err := range errs {
 | 
						|
		log.Error(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return len(errs) == 0
 | 
						|
}
 | 
						|
 | 
						|
// ValidateOnTui validates configuration
 | 
						|
func (c Config) ValidateOnTui() bool {
 | 
						|
	errs := []error{}
 | 
						|
 | 
						|
	if len(c.ResultsDir) != 0 {
 | 
						|
		if ok, _ := valid.IsFilePath(c.ResultsDir); !ok {
 | 
						|
			errs = append(errs, xerrors.Errorf(
 | 
						|
				"JSON base directory must be a *Absolute* file path. -results-dir: %s", c.ResultsDir))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if err := validateDB("cvedb", c.CveDict.Type, c.CveDict.SQLite3Path, c.CveDict.URL); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, err := range errs {
 | 
						|
		log.Error(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return len(errs) == 0
 | 
						|
}
 | 
						|
 | 
						|
// validateDB validates configuration
 | 
						|
//  dictionaryDB name is 'cvedb' or 'ovaldb'
 | 
						|
func validateDB(dictionaryDBName, dbType, dbPath, dbURL string) error {
 | 
						|
	log.Infof("-%s-type: %s, -%s-url: %s, -%s-path: %s",
 | 
						|
		dictionaryDBName, dbType, dictionaryDBName, dbURL, dictionaryDBName, dbPath)
 | 
						|
 | 
						|
	switch dbType {
 | 
						|
	case "sqlite3":
 | 
						|
		if dbURL != "" {
 | 
						|
			return xerrors.Errorf("To use SQLite3, specify -%s-type=sqlite3 and -%s-path. To use as http server mode, specify -%s-type=http and -%s-url",
 | 
						|
				dictionaryDBName, dictionaryDBName, dictionaryDBName, dictionaryDBName)
 | 
						|
		}
 | 
						|
		if ok, _ := valid.IsFilePath(dbPath); !ok {
 | 
						|
			return xerrors.Errorf("SQLite3 path must be a *Absolute* file path. -%s-path: %s",
 | 
						|
				dictionaryDBName, dbPath)
 | 
						|
		}
 | 
						|
	case "mysql":
 | 
						|
		if dbURL == "" {
 | 
						|
			return xerrors.Errorf(`MySQL connection string is needed. -%s-url="user:pass@tcp(localhost:3306)/dbname"`,
 | 
						|
				dictionaryDBName)
 | 
						|
		}
 | 
						|
	case "postgres":
 | 
						|
		if dbURL == "" {
 | 
						|
			return xerrors.Errorf(`PostgreSQL connection string is needed. -%s-url="host=myhost user=user dbname=dbname sslmode=disable password=password"`,
 | 
						|
				dictionaryDBName)
 | 
						|
		}
 | 
						|
	case "redis":
 | 
						|
		if dbURL == "" {
 | 
						|
			return xerrors.Errorf(`Redis connection string is needed. -%s-url="redis://localhost/0"`,
 | 
						|
				dictionaryDBName)
 | 
						|
		}
 | 
						|
	case "http":
 | 
						|
		if dbURL == "" {
 | 
						|
			return xerrors.Errorf(`URL is needed. -%s-url="http://localhost:1323"`,
 | 
						|
				dictionaryDBName)
 | 
						|
		}
 | 
						|
	default:
 | 
						|
		return xerrors.Errorf("%s type must be either 'sqlite3', 'mysql', 'postgres', 'redis' or 'http'.  -%s-type: %s",
 | 
						|
			dictionaryDBName, dictionaryDBName, dbType)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// SMTPConf is smtp config
 | 
						|
type SMTPConf struct {
 | 
						|
	SMTPAddr      string   `toml:"smtpAddr,omitempty" json:"-"`
 | 
						|
	SMTPPort      string   `toml:"smtpPort,omitempty" valid:"port" json:"-"`
 | 
						|
	User          string   `toml:"user,omitempty" json:"-"`
 | 
						|
	Password      string   `toml:"password,omitempty" json:"-"`
 | 
						|
	From          string   `toml:"from,omitempty" json:"-"`
 | 
						|
	To            []string `toml:"to,omitempty" json:"-"`
 | 
						|
	Cc            []string `toml:"cc,omitempty" json:"-"`
 | 
						|
	SubjectPrefix string   `toml:"subjectPrefix,omitempty" json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
func checkEmails(emails []string) (errs []error) {
 | 
						|
	for _, addr := range emails {
 | 
						|
		if len(addr) == 0 {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		if ok := valid.IsEmail(addr); !ok {
 | 
						|
			errs = append(errs, xerrors.Errorf("Invalid email address. email: %s", addr))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// Validate SMTP configuration
 | 
						|
func (c *SMTPConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToEmail {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	// Check Emails fromat
 | 
						|
	emails := []string{}
 | 
						|
	emails = append(emails, c.From)
 | 
						|
	emails = append(emails, c.To...)
 | 
						|
	emails = append(emails, c.Cc...)
 | 
						|
 | 
						|
	if emailErrs := checkEmails(emails); 0 < len(emailErrs) {
 | 
						|
		errs = append(errs, emailErrs...)
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.SMTPAddr) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("email.smtpAddr must not be empty"))
 | 
						|
	}
 | 
						|
	if len(c.SMTPPort) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("email.smtpPort must not be empty"))
 | 
						|
	}
 | 
						|
	if len(c.To) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("email.To required at least one address"))
 | 
						|
	}
 | 
						|
	if len(c.From) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("email.From required at least one address"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// StrideConf is stride config
 | 
						|
type StrideConf struct {
 | 
						|
	HookURL   string `json:"-"`
 | 
						|
	AuthToken string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *StrideConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToStride {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.HookURL) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("stride.HookURL must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.AuthToken) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("stride.AuthToken must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// SlackConf is slack config
 | 
						|
type SlackConf struct {
 | 
						|
	HookURL     string   `valid:"url" json:"-" toml:"hookURL,omitempty"`
 | 
						|
	LegacyToken string   `json:"-" toml:"legacyToken,omitempty"`
 | 
						|
	Channel     string   `json:"-" toml:"channel,omitempty"`
 | 
						|
	IconEmoji   string   `json:"-" toml:"iconEmoji,omitempty"`
 | 
						|
	AuthUser    string   `json:"-" toml:"authUser,omitempty"`
 | 
						|
	NotifyUsers []string `toml:"notifyUsers,omitempty" json:"-"`
 | 
						|
	Text        string   `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *SlackConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToSlack {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.HookURL) == 0 && len(c.LegacyToken) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("slack.hookURL or slack.LegacyToken must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.Channel) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("slack.channel must not be empty"))
 | 
						|
	} else {
 | 
						|
		if !(strings.HasPrefix(c.Channel, "#") ||
 | 
						|
			c.Channel == "${servername}") {
 | 
						|
			errs = append(errs, xerrors.Errorf(
 | 
						|
				"channel's prefix must be '#', channel: %s", c.Channel))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.AuthUser) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("slack.authUser must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// HipChatConf is HipChat config
 | 
						|
type HipChatConf struct {
 | 
						|
	AuthToken string `json:"-"`
 | 
						|
	Room      string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *HipChatConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToHipChat {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if len(c.Room) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("hipchat.room must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.AuthToken) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("hipchat.AuthToken must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// ChatWorkConf is ChatWork config
 | 
						|
type ChatWorkConf struct {
 | 
						|
	APIToken string `json:"-"`
 | 
						|
	Room     string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *ChatWorkConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToChatWork {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if len(c.Room) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("chatWorkConf.room must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.APIToken) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("chatWorkConf.ApiToken must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// TelegramConf is Telegram config
 | 
						|
type TelegramConf struct {
 | 
						|
	Token  string `json:"-"`
 | 
						|
	ChatID string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *TelegramConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToTelegram {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if len(c.ChatID) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("TelegramConf.ChatID must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.Token) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("TelegramConf.Token must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// SaasConf is stride config
 | 
						|
type SaasConf struct {
 | 
						|
	GroupID int64  `json:"-"`
 | 
						|
	Token   string `json:"-"`
 | 
						|
	URL     string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *SaasConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToSaas {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if c.GroupID == 0 {
 | 
						|
		errs = append(errs, xerrors.New("saas.GroupID must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.Token) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("saas.Token must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(c.URL) == 0 {
 | 
						|
		errs = append(errs, xerrors.New("saas.URL must not be empty"))
 | 
						|
	}
 | 
						|
 | 
						|
	_, err := valid.ValidateStruct(c)
 | 
						|
	if err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
// SyslogConf is syslog config
 | 
						|
type SyslogConf struct {
 | 
						|
	Protocol string `json:"-"`
 | 
						|
	Host     string `valid:"host" json:"-"`
 | 
						|
	Port     string `valid:"port" json:"-"`
 | 
						|
	Severity string `json:"-"`
 | 
						|
	Facility string `json:"-"`
 | 
						|
	Tag      string `json:"-"`
 | 
						|
	Verbose  bool   `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *SyslogConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToSyslog {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	//  If protocol is empty, it will connect to the local syslog server.
 | 
						|
	if len(c.Protocol) > 0 && c.Protocol != "tcp" && c.Protocol != "udp" {
 | 
						|
		errs = append(errs, errors.New(`syslog.protocol must be "tcp" or "udp"`))
 | 
						|
	}
 | 
						|
 | 
						|
	// Default port: 514
 | 
						|
	if c.Port == "" {
 | 
						|
		c.Port = "514"
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := c.GetSeverity(); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := c.GetFacility(); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := valid.ValidateStruct(c); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return errs
 | 
						|
}
 | 
						|
 | 
						|
// GetSeverity gets severity
 | 
						|
func (c *SyslogConf) GetSeverity() (syslog.Priority, error) {
 | 
						|
	if c.Severity == "" {
 | 
						|
		return syslog.LOG_INFO, nil
 | 
						|
	}
 | 
						|
 | 
						|
	switch c.Severity {
 | 
						|
	case "emerg":
 | 
						|
		return syslog.LOG_EMERG, nil
 | 
						|
	case "alert":
 | 
						|
		return syslog.LOG_ALERT, nil
 | 
						|
	case "crit":
 | 
						|
		return syslog.LOG_CRIT, nil
 | 
						|
	case "err":
 | 
						|
		return syslog.LOG_ERR, nil
 | 
						|
	case "warning":
 | 
						|
		return syslog.LOG_WARNING, nil
 | 
						|
	case "notice":
 | 
						|
		return syslog.LOG_NOTICE, nil
 | 
						|
	case "info":
 | 
						|
		return syslog.LOG_INFO, nil
 | 
						|
	case "debug":
 | 
						|
		return syslog.LOG_DEBUG, nil
 | 
						|
	default:
 | 
						|
		return -1, xerrors.Errorf("Invalid severity: %s", c.Severity)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GetFacility gets facility
 | 
						|
func (c *SyslogConf) GetFacility() (syslog.Priority, error) {
 | 
						|
	if c.Facility == "" {
 | 
						|
		return syslog.LOG_AUTH, nil
 | 
						|
	}
 | 
						|
 | 
						|
	switch c.Facility {
 | 
						|
	case "kern":
 | 
						|
		return syslog.LOG_KERN, nil
 | 
						|
	case "user":
 | 
						|
		return syslog.LOG_USER, nil
 | 
						|
	case "mail":
 | 
						|
		return syslog.LOG_MAIL, nil
 | 
						|
	case "daemon":
 | 
						|
		return syslog.LOG_DAEMON, nil
 | 
						|
	case "auth":
 | 
						|
		return syslog.LOG_AUTH, nil
 | 
						|
	case "syslog":
 | 
						|
		return syslog.LOG_SYSLOG, nil
 | 
						|
	case "lpr":
 | 
						|
		return syslog.LOG_LPR, nil
 | 
						|
	case "news":
 | 
						|
		return syslog.LOG_NEWS, nil
 | 
						|
	case "uucp":
 | 
						|
		return syslog.LOG_UUCP, nil
 | 
						|
	case "cron":
 | 
						|
		return syslog.LOG_CRON, nil
 | 
						|
	case "authpriv":
 | 
						|
		return syslog.LOG_AUTHPRIV, nil
 | 
						|
	case "ftp":
 | 
						|
		return syslog.LOG_FTP, nil
 | 
						|
	case "local0":
 | 
						|
		return syslog.LOG_LOCAL0, nil
 | 
						|
	case "local1":
 | 
						|
		return syslog.LOG_LOCAL1, nil
 | 
						|
	case "local2":
 | 
						|
		return syslog.LOG_LOCAL2, nil
 | 
						|
	case "local3":
 | 
						|
		return syslog.LOG_LOCAL3, nil
 | 
						|
	case "local4":
 | 
						|
		return syslog.LOG_LOCAL4, nil
 | 
						|
	case "local5":
 | 
						|
		return syslog.LOG_LOCAL5, nil
 | 
						|
	case "local6":
 | 
						|
		return syslog.LOG_LOCAL6, nil
 | 
						|
	case "local7":
 | 
						|
		return syslog.LOG_LOCAL7, nil
 | 
						|
	default:
 | 
						|
		return -1, xerrors.Errorf("Invalid facility: %s", c.Facility)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// HTTPConf is HTTP config
 | 
						|
type HTTPConf struct {
 | 
						|
	URL string `valid:"url" json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// Validate validates configuration
 | 
						|
func (c *HTTPConf) Validate() (errs []error) {
 | 
						|
	if !Conf.ToHTTP {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := valid.ValidateStruct(c); err != nil {
 | 
						|
		errs = append(errs, err)
 | 
						|
	}
 | 
						|
	return errs
 | 
						|
}
 | 
						|
 | 
						|
const httpKey = "VULS_HTTP_URL"
 | 
						|
 | 
						|
// Overwrite set options with the following priority.
 | 
						|
// 1. Command line option
 | 
						|
// 2. Environment variable
 | 
						|
// 3. config.toml
 | 
						|
func (c *HTTPConf) Overwrite(cmdOpt HTTPConf) {
 | 
						|
	if os.Getenv(httpKey) != "" {
 | 
						|
		c.URL = os.Getenv(httpKey)
 | 
						|
	}
 | 
						|
	if cmdOpt.URL != "" {
 | 
						|
		c.URL = cmdOpt.URL
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// GoCveDictConf is go-cve-dictionary config
 | 
						|
type GoCveDictConf struct {
 | 
						|
	// DB type of CVE dictionary (sqlite3, mysql, postgres or redis)
 | 
						|
	Type string
 | 
						|
 | 
						|
	// http://cve-dictionary.com:1323 or DB connection string
 | 
						|
	URL string `json:"-"`
 | 
						|
 | 
						|
	// /path/to/cve.sqlite3
 | 
						|
	SQLite3Path string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
func (cnf *GoCveDictConf) setDefault() {
 | 
						|
	if cnf.Type == "" {
 | 
						|
		cnf.Type = "sqlite3"
 | 
						|
	}
 | 
						|
	if cnf.URL == "" && cnf.SQLite3Path == "" {
 | 
						|
		wd, _ := os.Getwd()
 | 
						|
		cnf.SQLite3Path = filepath.Join(wd, "cve.sqlite3")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const cveDBType = "CVEDB_TYPE"
 | 
						|
const cveDBURL = "CVEDB_URL"
 | 
						|
const cveDBPATH = "CVEDB_SQLITE3_PATH"
 | 
						|
 | 
						|
// Overwrite set options with the following priority.
 | 
						|
// 1. Command line option
 | 
						|
// 2. Environment variable
 | 
						|
// 3. config.toml
 | 
						|
func (cnf *GoCveDictConf) Overwrite(cmdOpt GoCveDictConf) {
 | 
						|
	if os.Getenv(cveDBType) != "" {
 | 
						|
		cnf.Type = os.Getenv(cveDBType)
 | 
						|
	}
 | 
						|
	if os.Getenv(cveDBURL) != "" {
 | 
						|
		cnf.URL = os.Getenv(cveDBURL)
 | 
						|
	}
 | 
						|
	if os.Getenv(cveDBPATH) != "" {
 | 
						|
		cnf.SQLite3Path = os.Getenv(cveDBPATH)
 | 
						|
	}
 | 
						|
 | 
						|
	if cmdOpt.Type != "" {
 | 
						|
		cnf.Type = cmdOpt.Type
 | 
						|
	}
 | 
						|
	if cmdOpt.URL != "" {
 | 
						|
		cnf.URL = cmdOpt.URL
 | 
						|
	}
 | 
						|
	if cmdOpt.SQLite3Path != "" {
 | 
						|
		cnf.SQLite3Path = cmdOpt.SQLite3Path
 | 
						|
	}
 | 
						|
	cnf.setDefault()
 | 
						|
}
 | 
						|
 | 
						|
// IsFetchViaHTTP returns wether fetch via http
 | 
						|
func (cnf *GoCveDictConf) IsFetchViaHTTP() bool {
 | 
						|
	return Conf.CveDict.Type == "http"
 | 
						|
}
 | 
						|
 | 
						|
// GovalDictConf is goval-dictionary config
 | 
						|
type GovalDictConf struct {
 | 
						|
 | 
						|
	// DB type of OVAL dictionary (sqlite3, mysql, postgres or redis)
 | 
						|
	Type string
 | 
						|
 | 
						|
	// http://goval-dictionary.com:1324 or DB connection string
 | 
						|
	URL string `json:"-"`
 | 
						|
 | 
						|
	// /path/to/oval.sqlite3
 | 
						|
	SQLite3Path string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
func (cnf *GovalDictConf) setDefault() {
 | 
						|
	if cnf.Type == "" {
 | 
						|
		cnf.Type = "sqlite3"
 | 
						|
	}
 | 
						|
	if cnf.URL == "" && cnf.SQLite3Path == "" {
 | 
						|
		wd, _ := os.Getwd()
 | 
						|
		cnf.SQLite3Path = filepath.Join(wd, "oval.sqlite3")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const govalType = "OVALDB_TYPE"
 | 
						|
const govalURL = "OVALDB_URL"
 | 
						|
const govalPATH = "OVALDB_SQLITE3_PATH"
 | 
						|
 | 
						|
// Overwrite set options with the following priority.
 | 
						|
// 1. Command line option
 | 
						|
// 2. Environment variable
 | 
						|
// 3. config.toml
 | 
						|
func (cnf *GovalDictConf) Overwrite(cmdOpt GovalDictConf) {
 | 
						|
	if os.Getenv(govalType) != "" {
 | 
						|
		cnf.Type = os.Getenv(govalType)
 | 
						|
	}
 | 
						|
	if os.Getenv(govalURL) != "" {
 | 
						|
		cnf.URL = os.Getenv(govalURL)
 | 
						|
	}
 | 
						|
	if os.Getenv(govalPATH) != "" {
 | 
						|
		cnf.SQLite3Path = os.Getenv(govalPATH)
 | 
						|
	}
 | 
						|
 | 
						|
	if cmdOpt.Type != "" {
 | 
						|
		cnf.Type = cmdOpt.Type
 | 
						|
	}
 | 
						|
	if cmdOpt.URL != "" {
 | 
						|
		cnf.URL = cmdOpt.URL
 | 
						|
	}
 | 
						|
	if cmdOpt.SQLite3Path != "" {
 | 
						|
		cnf.SQLite3Path = cmdOpt.SQLite3Path
 | 
						|
	}
 | 
						|
	cnf.setDefault()
 | 
						|
}
 | 
						|
 | 
						|
// IsFetchViaHTTP returns wether fetch via http
 | 
						|
func (cnf *GovalDictConf) IsFetchViaHTTP() bool {
 | 
						|
	return Conf.OvalDict.Type == "http"
 | 
						|
}
 | 
						|
 | 
						|
// GostConf is gost config
 | 
						|
type GostConf struct {
 | 
						|
	// DB type for gost dictionary (sqlite3, mysql, postgres or redis)
 | 
						|
	Type string
 | 
						|
 | 
						|
	// http://gost-dictionary.com:1324 or DB connection string
 | 
						|
	URL string `json:"-"`
 | 
						|
 | 
						|
	// /path/to/gost.sqlite3
 | 
						|
	SQLite3Path string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
func (cnf *GostConf) setDefault() {
 | 
						|
	if cnf.Type == "" {
 | 
						|
		cnf.Type = "sqlite3"
 | 
						|
	}
 | 
						|
	if cnf.URL == "" && cnf.SQLite3Path == "" {
 | 
						|
		wd, _ := os.Getwd()
 | 
						|
		cnf.SQLite3Path = filepath.Join(wd, "gost.sqlite3")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const gostDBType = "GOSTDB_TYPE"
 | 
						|
const gostDBURL = "GOSTDB_URL"
 | 
						|
const gostDBPATH = "GOSTDB_SQLITE3_PATH"
 | 
						|
 | 
						|
// Overwrite set options with the following priority.
 | 
						|
// 1. Command line option
 | 
						|
// 2. Environment variable
 | 
						|
// 3. config.toml
 | 
						|
func (cnf *GostConf) Overwrite(cmdOpt GostConf) {
 | 
						|
	if os.Getenv(gostDBType) != "" {
 | 
						|
		cnf.Type = os.Getenv(gostDBType)
 | 
						|
	}
 | 
						|
	if os.Getenv(gostDBURL) != "" {
 | 
						|
		cnf.URL = os.Getenv(gostDBURL)
 | 
						|
	}
 | 
						|
	if os.Getenv(gostDBPATH) != "" {
 | 
						|
		cnf.SQLite3Path = os.Getenv(gostDBPATH)
 | 
						|
	}
 | 
						|
 | 
						|
	if cmdOpt.Type != "" {
 | 
						|
		cnf.Type = cmdOpt.Type
 | 
						|
	}
 | 
						|
	if cmdOpt.URL != "" {
 | 
						|
		cnf.URL = cmdOpt.URL
 | 
						|
	}
 | 
						|
	if cmdOpt.SQLite3Path != "" {
 | 
						|
		cnf.SQLite3Path = cmdOpt.SQLite3Path
 | 
						|
	}
 | 
						|
	cnf.setDefault()
 | 
						|
}
 | 
						|
 | 
						|
// IsFetchViaHTTP returns wether fetch via http
 | 
						|
func (cnf *GostConf) IsFetchViaHTTP() bool {
 | 
						|
	return Conf.Gost.Type == "http"
 | 
						|
}
 | 
						|
 | 
						|
// ExploitConf is exploit config
 | 
						|
type ExploitConf struct {
 | 
						|
	// DB type for exploit dictionary (sqlite3, mysql, postgres or redis)
 | 
						|
	Type string
 | 
						|
 | 
						|
	// http://exploit-dictionary.com:1324 or DB connection string
 | 
						|
	URL string `json:"-"`
 | 
						|
 | 
						|
	// /path/to/exploit.sqlite3
 | 
						|
	SQLite3Path string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
func (cnf *ExploitConf) setDefault() {
 | 
						|
	if cnf.Type == "" {
 | 
						|
		cnf.Type = "sqlite3"
 | 
						|
	}
 | 
						|
	if cnf.URL == "" && cnf.SQLite3Path == "" {
 | 
						|
		wd, _ := os.Getwd()
 | 
						|
		cnf.SQLite3Path = filepath.Join(wd, "go-exploitdb.sqlite3")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const exploitDBType = "EXPLOITDB_TYPE"
 | 
						|
const exploitDBURL = "EXPLOITDB_URL"
 | 
						|
const exploitDBPATH = "EXPLOITDB_SQLITE3_PATH"
 | 
						|
 | 
						|
// Overwrite set options with the following priority.
 | 
						|
// 1. Command line option
 | 
						|
// 2. Environment variable
 | 
						|
// 3. config.toml
 | 
						|
func (cnf *ExploitConf) Overwrite(cmdOpt ExploitConf) {
 | 
						|
	if os.Getenv(exploitDBType) != "" {
 | 
						|
		cnf.Type = os.Getenv(exploitDBType)
 | 
						|
	}
 | 
						|
	if os.Getenv(exploitDBURL) != "" {
 | 
						|
		cnf.URL = os.Getenv(exploitDBURL)
 | 
						|
	}
 | 
						|
	if os.Getenv(exploitDBPATH) != "" {
 | 
						|
		cnf.SQLite3Path = os.Getenv(exploitDBPATH)
 | 
						|
	}
 | 
						|
 | 
						|
	if cmdOpt.Type != "" {
 | 
						|
		cnf.Type = cmdOpt.Type
 | 
						|
	}
 | 
						|
	if cmdOpt.URL != "" {
 | 
						|
		cnf.URL = cmdOpt.URL
 | 
						|
	}
 | 
						|
	if cmdOpt.SQLite3Path != "" {
 | 
						|
		cnf.SQLite3Path = cmdOpt.SQLite3Path
 | 
						|
	}
 | 
						|
	cnf.setDefault()
 | 
						|
}
 | 
						|
 | 
						|
// IsFetchViaHTTP returns wether fetch via http
 | 
						|
func (cnf *ExploitConf) IsFetchViaHTTP() bool {
 | 
						|
	return Conf.Exploit.Type == "http"
 | 
						|
}
 | 
						|
 | 
						|
// MetasploitConf is metasploit config
 | 
						|
type MetasploitConf struct {
 | 
						|
	// DB type for metasploit dictionary (sqlite3, mysql, postgres or redis)
 | 
						|
	Type string
 | 
						|
 | 
						|
	// http://metasploit-dictionary.com:1324 or DB connection string
 | 
						|
	URL string `json:"-"`
 | 
						|
 | 
						|
	// /path/to/metasploit.sqlite3
 | 
						|
	SQLite3Path string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
func (cnf *MetasploitConf) setDefault() {
 | 
						|
	if cnf.Type == "" {
 | 
						|
		cnf.Type = "sqlite3"
 | 
						|
	}
 | 
						|
	if cnf.URL == "" && cnf.SQLite3Path == "" {
 | 
						|
		wd, _ := os.Getwd()
 | 
						|
		cnf.SQLite3Path = filepath.Join(wd, "go-msfdb.sqlite3")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const metasploitDBType = "METASPLOITDB_TYPE"
 | 
						|
const metasploitDBURL = "METASPLOITDB_URL"
 | 
						|
const metasploitDBPATH = "METASPLOITDB_SQLITE3_PATH"
 | 
						|
 | 
						|
// Overwrite set options with the following priority.
 | 
						|
// 1. Command line option
 | 
						|
// 2. Environment variable
 | 
						|
// 3. config.toml
 | 
						|
func (cnf *MetasploitConf) Overwrite(cmdOpt MetasploitConf) {
 | 
						|
	if os.Getenv(metasploitDBType) != "" {
 | 
						|
		cnf.Type = os.Getenv(metasploitDBType)
 | 
						|
	}
 | 
						|
	if os.Getenv(metasploitDBURL) != "" {
 | 
						|
		cnf.URL = os.Getenv(metasploitDBURL)
 | 
						|
	}
 | 
						|
	if os.Getenv(metasploitDBPATH) != "" {
 | 
						|
		cnf.SQLite3Path = os.Getenv(metasploitDBPATH)
 | 
						|
	}
 | 
						|
 | 
						|
	if cmdOpt.Type != "" {
 | 
						|
		cnf.Type = cmdOpt.Type
 | 
						|
	}
 | 
						|
	if cmdOpt.URL != "" {
 | 
						|
		cnf.URL = cmdOpt.URL
 | 
						|
	}
 | 
						|
	if cmdOpt.SQLite3Path != "" {
 | 
						|
		cnf.SQLite3Path = cmdOpt.SQLite3Path
 | 
						|
	}
 | 
						|
	cnf.setDefault()
 | 
						|
}
 | 
						|
 | 
						|
// IsFetchViaHTTP returns wether fetch via http
 | 
						|
func (cnf *MetasploitConf) IsFetchViaHTTP() bool {
 | 
						|
	return Conf.Metasploit.Type == "http"
 | 
						|
}
 | 
						|
 | 
						|
// AWS is aws config
 | 
						|
type AWS struct {
 | 
						|
	// AWS profile to use
 | 
						|
	Profile string `json:"profile"`
 | 
						|
 | 
						|
	// AWS region to use
 | 
						|
	Region string `json:"region"`
 | 
						|
 | 
						|
	// S3 bucket name
 | 
						|
	S3Bucket string `json:"s3Bucket"`
 | 
						|
 | 
						|
	// /bucket/path/to/results
 | 
						|
	S3ResultsDir string `json:"s3ResultsDir"`
 | 
						|
 | 
						|
	// The Server-side encryption algorithm used when storing the reports in S3 (e.g., AES256, aws:kms).
 | 
						|
	S3ServerSideEncryption string `json:"s3ServerSideEncryption"`
 | 
						|
}
 | 
						|
 | 
						|
// Azure is azure config
 | 
						|
type Azure struct {
 | 
						|
	// Azure account name to use. AZURE_STORAGE_ACCOUNT environment variable is used if not specified
 | 
						|
	AccountName string `json:"accountName"`
 | 
						|
 | 
						|
	// Azure account key to use. AZURE_STORAGE_ACCESS_KEY environment variable is used if not specified
 | 
						|
	AccountKey string `json:"-"`
 | 
						|
 | 
						|
	// Azure storage container name
 | 
						|
	ContainerName string `json:"containerName"`
 | 
						|
}
 | 
						|
 | 
						|
// ServerInfo has SSH Info, additional CPE packages to scan.
 | 
						|
type ServerInfo struct {
 | 
						|
	ServerName             string                      `toml:"-" json:"serverName,omitempty"`
 | 
						|
	User                   string                      `toml:"user,omitempty" json:"user,omitempty"`
 | 
						|
	Host                   string                      `toml:"host,omitempty" json:"host,omitempty"`
 | 
						|
	JumpServer             []string                    `toml:"jumpServer,omitempty" json:"jumpServer,omitempty"`
 | 
						|
	Port                   string                      `toml:"port,omitempty" json:"port,omitempty"`
 | 
						|
	SSHConfigPath          string                      `toml:"sshConfigPath,omitempty" json:"sshConfigPath,omitempty"`
 | 
						|
	KeyPath                string                      `toml:"keyPath,omitempty" json:"keyPath,omitempty"`
 | 
						|
	KeyPassword            string                      `json:"-,omitempty" toml:"-"`
 | 
						|
	CpeNames               []string                    `toml:"cpeNames,omitempty" json:"cpeNames,omitempty"`
 | 
						|
	ScanMode               []string                    `toml:"scanMode,omitempty" json:"scanMode,omitempty"`
 | 
						|
	DependencyCheckXMLPath string                      `toml:"dependencyCheckXMLPath,omitempty" json:"-"` // TODO Deprecated remove in near future
 | 
						|
	OwaspDCXMLPath         string                      `toml:"owaspDCXMLPath,omitempty" json:"owaspDCXMLPath,omitempty"`
 | 
						|
	ContainersIncluded     []string                    `toml:"containersIncluded,omitempty" json:"containersIncluded,omitempty"`
 | 
						|
	ContainersExcluded     []string                    `toml:"containersExcluded,omitempty" json:"containersExcluded,omitempty"`
 | 
						|
	ContainerType          string                      `toml:"containerType,omitempty" json:"containerType,omitempty"`
 | 
						|
	Containers             map[string]ContainerSetting `toml:"containers" json:"containers,omitempty"`
 | 
						|
	IgnoreCves             []string                    `toml:"ignoreCves,omitempty" json:"ignoreCves,omitempty"`
 | 
						|
	IgnorePkgsRegexp       []string                    `toml:"ignorePkgsRegexp,omitempty" json:"ignorePkgsRegexp,omitempty"`
 | 
						|
	GitHubRepos            map[string]GitHubConf       `toml:"githubs" json:"githubs,omitempty"` // key: owner/repo
 | 
						|
	UUIDs                  map[string]string           `toml:"uuids,omitempty" json:"uuids,omitempty"`
 | 
						|
	Memo                   string                      `toml:"memo,omitempty" json:"memo,omitempty"`
 | 
						|
	Enablerepo             []string                    `toml:"enablerepo,omitempty" json:"enablerepo,omitempty"` // For CentOS, RHEL, Amazon
 | 
						|
	Optional               map[string]interface{}      `toml:"optional,omitempty" json:"optional,omitempty"`     // Optional key-value set that will be outputted to JSON
 | 
						|
	Lockfiles              []string                    `toml:"lockfiles,omitempty" json:"lockfiles,omitempty"`   // ie) path/to/package-lock.json
 | 
						|
	FindLock               bool                        `toml:"findLock,omitempty" json:"findLock,omitempty"`
 | 
						|
	Type                   string                      `toml:"type,omitempty" json:"type,omitempty"` // "pseudo" or ""
 | 
						|
 | 
						|
	WordPress WordPressConf `toml:"wordpress,omitempty" json:"wordpress,omitempty"`
 | 
						|
 | 
						|
	// used internal
 | 
						|
	IPv4Addrs      []string       `toml:"-" json:"ipv4Addrs,omitempty"`
 | 
						|
	IPv6Addrs      []string       `toml:"-" json:"ipv6Addrs,omitempty"`
 | 
						|
	IPSIdentifiers map[IPS]string `toml:"-" json:"ipsIdentifiers,omitempty"`
 | 
						|
 | 
						|
	LogMsgAnsiColor string    `toml:"-" json:"-"` // DebugLog Color
 | 
						|
	Container       Container `toml:"-" json:"-"`
 | 
						|
	Distro          Distro    `toml:"-" json:"-"`
 | 
						|
	Mode            ScanMode  `toml:"-" json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// ContainerSetting is used for loading container setting in config.toml
 | 
						|
type ContainerSetting struct {
 | 
						|
	Cpes             []string `json:"cpes,omitempty"`
 | 
						|
	OwaspDCXMLPath   string   `json:"owaspDCXMLPath"`
 | 
						|
	IgnorePkgsRegexp []string `json:"ignorePkgsRegexp,omitempty"`
 | 
						|
	IgnoreCves       []string `json:"ignoreCves,omitempty"`
 | 
						|
}
 | 
						|
 | 
						|
// WordPressConf used for WordPress Scanning
 | 
						|
type WordPressConf struct {
 | 
						|
	OSUser         string `toml:"osUser" json:"osUser,omitempty"`
 | 
						|
	DocRoot        string `toml:"docRoot" json:"docRoot,omitempty"`
 | 
						|
	CmdPath        string `toml:"cmdPath" json:"cmdPath,omitempty"`
 | 
						|
	WPVulnDBToken  string `toml:"wpVulnDBToken" json:"-,omitempty"`
 | 
						|
	IgnoreInactive bool   `json:"ignoreInactive,omitempty"`
 | 
						|
}
 | 
						|
 | 
						|
// GitHubConf is used for GitHub integration
 | 
						|
type GitHubConf struct {
 | 
						|
	Token string `json:"-"`
 | 
						|
}
 | 
						|
 | 
						|
// ScanMode has a type of scan mode. fast, fast-root, deep and offline
 | 
						|
type ScanMode struct {
 | 
						|
	flag byte
 | 
						|
}
 | 
						|
 | 
						|
// Set mode
 | 
						|
func (s *ScanMode) Set(f byte) {
 | 
						|
	s.flag |= f
 | 
						|
}
 | 
						|
 | 
						|
// IsFast return whether scan mode is fast
 | 
						|
func (s ScanMode) IsFast() bool {
 | 
						|
	return s.flag&Fast == Fast
 | 
						|
}
 | 
						|
 | 
						|
// IsFastRoot return whether scan mode is fastroot
 | 
						|
func (s ScanMode) IsFastRoot() bool {
 | 
						|
	return s.flag&FastRoot == FastRoot
 | 
						|
}
 | 
						|
 | 
						|
// IsDeep return whether scan mode is deep
 | 
						|
func (s ScanMode) IsDeep() bool {
 | 
						|
	return s.flag&Deep == Deep
 | 
						|
}
 | 
						|
 | 
						|
// IsOffline return whether scan mode is offline
 | 
						|
func (s ScanMode) IsOffline() bool {
 | 
						|
	return s.flag&Offline == Offline
 | 
						|
}
 | 
						|
 | 
						|
func (s ScanMode) validate() error {
 | 
						|
	numTrue := 0
 | 
						|
	for _, b := range []bool{s.IsFast(), s.IsFastRoot(), s.IsDeep()} {
 | 
						|
		if b {
 | 
						|
			numTrue++
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if numTrue == 0 {
 | 
						|
		s.Set(Fast)
 | 
						|
	} else if s.IsDeep() && s.IsOffline() {
 | 
						|
		return xerrors.New("Don't specify both of -deep and offline")
 | 
						|
	} else if numTrue != 1 {
 | 
						|
		return xerrors.New("Specify only one of -fast, -fast-root or -deep")
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (s ScanMode) String() string {
 | 
						|
	ss := ""
 | 
						|
	if s.IsFast() {
 | 
						|
		ss = "fast"
 | 
						|
	} else if s.IsFastRoot() {
 | 
						|
		ss = "fast-root"
 | 
						|
	} else if s.IsDeep() {
 | 
						|
		ss = "deep"
 | 
						|
	}
 | 
						|
	if s.IsOffline() {
 | 
						|
		ss += " offline"
 | 
						|
	}
 | 
						|
	return ss + " mode"
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	// Fast is fast scan mode
 | 
						|
	Fast = byte(1 << iota)
 | 
						|
	// FastRoot is fast-root scan mode
 | 
						|
	FastRoot
 | 
						|
	// Deep is deep scan mode
 | 
						|
	Deep
 | 
						|
	// Offline is offline scan mode
 | 
						|
	Offline
 | 
						|
)
 | 
						|
 | 
						|
// GetServerName returns ServerName if this serverInfo is about host.
 | 
						|
// If this serverInfo is about a container, returns containerID@ServerName
 | 
						|
func (s ServerInfo) GetServerName() string {
 | 
						|
	if len(s.Container.ContainerID) == 0 {
 | 
						|
		return s.ServerName
 | 
						|
	}
 | 
						|
	return fmt.Sprintf("%s@%s", s.Container.Name, s.ServerName)
 | 
						|
}
 | 
						|
 | 
						|
// Distro has distribution info
 | 
						|
type Distro struct {
 | 
						|
	Family  string
 | 
						|
	Release string
 | 
						|
}
 | 
						|
 | 
						|
func (l Distro) String() string {
 | 
						|
	return fmt.Sprintf("%s %s", l.Family, l.Release)
 | 
						|
}
 | 
						|
 | 
						|
// MajorVersion returns Major version
 | 
						|
func (l Distro) MajorVersion() (int, error) {
 | 
						|
	if l.Family == Amazon {
 | 
						|
		ss := strings.Fields(l.Release)
 | 
						|
		if len(ss) == 1 {
 | 
						|
			return 1, nil
 | 
						|
		}
 | 
						|
		return strconv.Atoi(ss[0])
 | 
						|
	}
 | 
						|
	if 0 < len(l.Release) {
 | 
						|
		return strconv.Atoi(strings.Split(l.Release, ".")[0])
 | 
						|
	}
 | 
						|
	return 0, xerrors.New("Release is empty")
 | 
						|
}
 | 
						|
 | 
						|
// IsContainer returns whether this ServerInfo is about container
 | 
						|
func (s ServerInfo) IsContainer() bool {
 | 
						|
	return 0 < len(s.Container.ContainerID)
 | 
						|
}
 | 
						|
 | 
						|
// SetContainer set container
 | 
						|
func (s *ServerInfo) SetContainer(d Container) {
 | 
						|
	s.Container = d
 | 
						|
}
 | 
						|
 | 
						|
// Container has Container information.
 | 
						|
type Container struct {
 | 
						|
	ContainerID string
 | 
						|
	Name        string
 | 
						|
	Image       string
 | 
						|
}
 |