// Command-line interface package cmd import ( "compress/gzip" "encoding/json" "encoding/xml" "github.com/pablotron/cvez/cisa" "github.com/pablotron/cvez/cpedict" "github.com/pablotron/cvez/cpematch" "github.com/pablotron/cvez/datadir" "github.com/pablotron/cvez/dbstore" "github.com/pablotron/cvez/nvdmirror" "github.com/rs/zerolog" "github.com/rs/zerolog/log" nvd_feed "github.com/pablotron/cvez/feed" "os" "path/filepath" "strings" "time" ) // Build query string. func getSearchQuery(args []string) string { r := make([]string, len(args)) for i, v := range(args) { r[i] = "\"" + strings.ReplaceAll(strings.ToLower(v), "\"", "\"\"") + "\"" } return strings.Join(r, " AND ") } // Get database store. func getDb() dbstore.DbStore { // build database path dbPath, err := datadir.Join("cvez.db") if err != nil { log.Error().Err(err).Msg("Join") os.Exit(-1) } // open database db, err := dbstore.Open(dbPath) if err != nil { log.Error().Err(err).Msg("Open") os.Exit(-1) } return db } // Get cache and cache directory path. func getCache() (nvdmirror.JsonCache, string) { // get path to cache directory dir, err := datadir.CacheDir() if err != nil { log.Error().Err(err).Msg("CacheDir") os.Exit(-1) } // build cache file path cachePath := filepath.Join(dir, "cache.json.gz") // create cache cache, err := nvdmirror.NewJsonCache(cachePath) if err != nil { log.Error().Err(err).Msg("NewJsonCache") os.Exit(-1) } // return cache return cache, dir } // JSON encode data and write it to standard output func jsonEncode(data interface{}) { // search for CVEs, write result e := json.NewEncoder(os.Stdout) if err := e.Encode(data); err != nil { log.Error().Err(err).Msg("Encode") os.Exit(-1) } } func init() { // set global logging options zerolog.TimeFieldFormat = time.RFC3339 zerolog.SetGlobalLevel(zerolog.InfoLevel) rootCmd.AddCommand(searchCmd) rootCmd.AddCommand(cisaSearchCmd) rootCmd.AddCommand(cvssCmd) rootCmd.AddCommand(updateCmd) } // read gzipped file, pass reader to callback. func gzOpen(path string, fn func(*gzip.Reader)) { f, err := os.Open(path) if err != nil { log.Error().Err(err).Msg("Open") os.Exit(-1) } defer f.Close() // create gzip reader r, err := gzip.NewReader(f) if err != nil { log.Error().Err(err).Msg("NewReader") os.Exit(-1) } fn(r) } // read gzipped json, pass decoder to callback func jsonGzOpen(path string, fn func(*json.Decoder)) { gzOpen(path, func(r *gzip.Reader) { fn(json.NewDecoder(r)) }) } // read gzipped xml, pass decoder to callback func xmlGzOpen(path string, fn func(*xml.Decoder)) { gzOpen(path, func(r *gzip.Reader) { fn(xml.NewDecoder(r)) }) } // Read feed from file. func getFeed(path string) nvd_feed.Feed { var feed nvd_feed.Feed jsonGzOpen(path, func(d *json.Decoder) { if err := d.Decode(&feed); err != nil { log.Error().Err(err).Msg("Decode") os.Exit(-1) } }) // return feed return feed } // Read cpe matches from file. func getCpeMatches(path string) cpematch.Matches { var matches cpematch.Matches jsonGzOpen(path, func(d *json.Decoder) { if err := d.Decode(&matches); err != nil { log.Error().Err(err).Msg("Decode") os.Exit(-1) } }) // return matches return matches } // Read cpe dictionary from file. func getCpeDict(path string) cpedict.Dictionary { var dict cpedict.Dictionary xmlGzOpen(path, func(d *xml.Decoder) { if err := d.Decode(&dict); err != nil { log.Error().Err(err).Msg("Decode") os.Exit(-1) } }) // return dictionary return dict } // Read cisa catalog from file. func getCisaCatalog(path string) cisa.Catalog { f, err := os.Open(path) if err != nil { log.Error().Err(err).Msg("Open") os.Exit(-1) } defer f.Close() // create decoder, decode catalog var cat cisa.Catalog d := json.NewDecoder(f) if err = d.Decode(&cat); err != nil { log.Error().Err(err).Msg("Decode") os.Exit(-1) } // return catalog return cat }