Ejemplo n.º 1
0
func updateRepository(pathToRepo string) (int, error) {
	// Pull repository
	out, err := utils.Exec(pathToRepo, "bzr", "pull", "--overwrite")
	if err != nil {
		log.Errorf("could not pull Ubuntu repository: %s. output: %s", err, string(out))
		return 0, cerrors.ErrCouldNotDownload
	}

	// Get revision number
	if strings.Contains(string(out), "No revisions or tags to pull") {
		out, _ = utils.Exec(pathToRepo, "bzr", "revno")
		revno, err := strconv.Atoi(string(out[:len(out)-1]))
		if err != nil {
			log.Errorf("could not parse Ubuntu repository revision number: %s. output: %s", err, string(out))
			return 0, cerrors.ErrCouldNotDownload
		}
		return revno, nil
	}

	regexpMatches := revisionRegexp.FindStringSubmatch(string(out))
	if len(regexpMatches) != 2 {
		log.Error("could not parse bzr pull output to get the revision number")
		return 0, cerrors.ErrCouldNotDownload
	}

	revno, err := strconv.Atoi(regexpMatches[1])
	if err != nil {
		log.Error("could not parse bzr pull output to get the revision number")
		return 0, cerrors.ErrCouldNotDownload
	}

	return revno, nil
}
Ejemplo n.º 2
0
func (f *fetcher) pullRepository() (commit string, err error) {
	// If the repository doesn't exist, clone it.
	if _, pathExists := os.Stat(f.repositoryLocalPath); f.repositoryLocalPath == "" || os.IsNotExist(pathExists) {
		if f.repositoryLocalPath, err = ioutil.TempDir(os.TempDir(), "alpine-secdb"); err != nil {
			return "", ErrFilesystem
		}

		if out, err := utils.Exec(f.repositoryLocalPath, "git", "clone", secdbGitURL, "."); err != nil {
			f.Clean()
			log.Errorf("could not pull alpine-secdb repository: %s. output: %s", err, out)
			return "", cerrors.ErrCouldNotDownload
		}
	} else {
		// The repository exists and it needs to be refreshed via a pull.
		_, err := utils.Exec(f.repositoryLocalPath, "git", "pull")
		if err != nil {
			return "", ErrGitFailure
		}
	}

	out, err := utils.Exec(f.repositoryLocalPath, "git", "rev-parse", "HEAD")
	if err != nil {
		return "", ErrGitFailure
	}

	commit = strings.TrimSpace(string(out))
	return
}
Ejemplo n.º 3
0
func (fetcher *UbuntuFetcher) pullRepository() (err error) {
	// Determine whether we should branch or pull.
	if _, pathExists := os.Stat(fetcher.repositoryLocalPath); fetcher.repositoryLocalPath == "" || os.IsNotExist(pathExists) {
		// Create a temporary folder to store the repository.
		if fetcher.repositoryLocalPath, err = ioutil.TempDir(os.TempDir(), "ubuntu-cve-tracker"); err != nil {
			return ErrFilesystem
		}

		// Branch repository.
		if out, err := utils.Exec(fetcher.repositoryLocalPath, "bzr", "branch", "--use-existing-dir", trackerRepository, "."); err != nil {
			log.Errorf("could not branch Ubuntu repository: %s. output: %s", err, out)
			return cerrors.ErrCouldNotDownload
		}

		return nil
	}

	// Pull repository.
	if out, err := utils.Exec(fetcher.repositoryLocalPath, "bzr", "pull", "--overwrite"); err != nil {
		os.RemoveAll(fetcher.repositoryLocalPath)

		log.Errorf("could not pull Ubuntu repository: %s. output: %s", err, out)
		return cerrors.ErrCouldNotDownload
	}

	return nil
}
Ejemplo n.º 4
0
func collectModifiedVulnerabilities(revision int, dbRevision, repositoryLocalPath string) (map[string]struct{}, error) {
	modifiedCVE := make(map[string]struct{})

	// Handle a brand new database.
	if dbRevision == "" {
		for _, folder := range []string{"active", "retired"} {
			d, err := os.Open(repositoryLocalPath + "/" + folder)
			if err != nil {
				log.Errorf("could not open Ubuntu vulnerabilities repository's folder: %s", err)
				return nil, ErrFilesystem
			}
			defer d.Close()

			// Get the FileInfo of all the files in the directory.
			names, err := d.Readdirnames(-1)
			if err != nil {
				log.Errorf("could not read Ubuntu vulnerabilities repository's folder:: %s.", err)
				return nil, ErrFilesystem
			}

			// Add the vulnerabilities to the list.
			for _, name := range names {
				if strings.HasPrefix(name, "CVE-") {
					modifiedCVE[folder+"/"+name] = struct{}{}
				}
			}
		}

		return modifiedCVE, nil
	}

	// Handle an up to date database.
	dbRevisionInt, _ := strconv.Atoi(dbRevision)
	if revision == dbRevisionInt {
		log.Debug("no Ubuntu update")
		return modifiedCVE, nil
	}

	// Handle a database that needs upgrading.
	out, err := utils.Exec(repositoryLocalPath, "bzr", "log", "--verbose", "-r"+strconv.Itoa(dbRevisionInt+1)+"..", "-n0")
	if err != nil {
		log.Errorf("could not get Ubuntu vulnerabilities repository logs: %s. output: %s", err, string(out))
		return nil, cerrors.ErrCouldNotDownload
	}

	scanner := bufio.NewScanner(bytes.NewReader(out))
	for scanner.Scan() {
		text := strings.TrimSpace(scanner.Text())
		if strings.Contains(text, "CVE-") && (strings.HasPrefix(text, "active/") || strings.HasPrefix(text, "retired/")) {
			if strings.Contains(text, " => ") {
				text = text[strings.Index(text, " => ")+4:]
			}
			modifiedCVE[text] = struct{}{}
		}
	}

	return modifiedCVE, nil
}
Ejemplo n.º 5
0
func updateRepository(pathToRepo string) error {
	// Pull repository
	out, err := utils.Exec(pathToRepo, "bzr", "pull", "--overwrite")
	if err != nil {
		log.Errorf("could not pull Ubuntu repository: %s. output: %s", err, out)
		return cerrors.ErrCouldNotDownload
	}
	return nil
}
Ejemplo n.º 6
0
func createRepository(pathToRepo string) error {
	// Branch repository
	out, err := utils.Exec("/tmp/", "bzr", "branch", trackerRepository, pathToRepo)
	if err != nil {
		log.Errorf("could not branch Ubuntu repository: %s. output: %s", err, out)
		return cerrors.ErrCouldNotDownload
	}
	return nil
}
Ejemplo n.º 7
0
func getRevisionNumber(pathToRepo string) (int, error) {
	out, err := utils.Exec(pathToRepo, "bzr", "revno")
	if err != nil {
		log.Errorf("could not get Ubuntu repository's revision number: %s. output: %s", err, out)
		return 0, cerrors.ErrCouldNotDownload
	}
	revno, err := strconv.Atoi(strings.TrimSpace(string(out)))
	if err != nil {
		log.Errorf("could not parse Ubuntu repository's revision number: %s. output: %s", err, out)
		return 0, cerrors.ErrCouldNotDownload
	}
	return revno, nil
}
Ejemplo n.º 8
0
func createRepository(pathToRepo string) (int, error) {
	// Branch repository
	out, err := utils.Exec("/tmp/", "bzr", "branch", ubuntuTracker, pathToRepo)
	if err != nil {
		log.Errorf("could not branch Ubuntu repository: %s. output: %s", err, string(out))
		return 0, cerrors.ErrCouldNotDownload
	}

	// Get revision number
	regexpMatches := branchedRegexp.FindStringSubmatch(string(out))
	if len(regexpMatches) != 2 {
		log.Error("could not parse bzr branch output to get the revision number")
		return 0, cerrors.ErrCouldNotDownload
	}

	revision, err := strconv.Atoi(regexpMatches[1])
	if err != nil {
		log.Error("could not parse bzr branch output to get the revision number")
		return 0, cerrors.ErrCouldNotDownload
	}

	return revision, err
}
Ejemplo n.º 9
0
// Detect detects packages using var/lib/rpm/Packages from the input data
func (detector *RpmFeaturesDetector) Detect(data map[string][]byte) ([]database.FeatureVersion, error) {
	f, hasFile := data["var/lib/rpm/Packages"]
	if !hasFile {
		return []database.FeatureVersion{}, nil
	}

	// Create a map to store packages and ensure their uniqueness
	packagesMap := make(map[string]database.FeatureVersion)

	// Write the required "Packages" file to disk
	tmpDir, err := ioutil.TempDir(os.TempDir(), "rpm")
	defer os.RemoveAll(tmpDir)
	if err != nil {
		log.Errorf("could not create temporary folder for RPM detection: %s", err)
		return []database.FeatureVersion{}, cerrors.ErrFilesystem
	}

	err = ioutil.WriteFile(tmpDir+"/Packages", f, 0700)
	if err != nil {
		log.Errorf("could not create temporary file for RPM detection: %s", err)
		return []database.FeatureVersion{}, cerrors.ErrFilesystem
	}

	// Query RPM
	// We actually extract binary package names instead of source package names here because RHSA refers to package names
	// In the dpkg system, we extract the source instead
	out, err := utils.Exec(tmpDir, "rpm", "--dbpath", tmpDir, "-qa", "--qf", "%{NAME} %{EPOCH}:%{VERSION}-%{RELEASE}\n")
	if err != nil {
		log.Errorf("could not query RPM: %s. output: %s", err, string(out))
		// Do not bubble up because we probably won't be able to fix it,
		// the database must be corrupted
		return []database.FeatureVersion{}, nil
	}

	scanner := bufio.NewScanner(strings.NewReader(string(out)))
	for scanner.Scan() {
		line := strings.Split(scanner.Text(), " ")
		if len(line) != 2 {
			// We may see warnings on some RPM versions:
			// "warning: Generating 12 missing index(es), please wait..."
			continue
		}

		// Ignore gpg-pubkey packages which are fake packages used to store GPG keys - they are not versionned properly.
		if line[0] == "gpg-pubkey" {
			continue
		}

		// Parse version
		version, err := types.NewVersion(strings.Replace(line[1], "(none):", "", -1))
		if err != nil {
			log.Warningf("could not parse package version '%s': %s. skipping", line[1], err.Error())
			continue
		}

		// Add package
		pkg := database.FeatureVersion{
			Feature: database.Feature{
				Name: line[0],
			},
			Version: version,
		}
		packagesMap[pkg.Feature.Name+"#"+pkg.Version.String()] = pkg
	}

	// Convert the map to a slice
	packages := make([]database.FeatureVersion, 0, len(packagesMap))
	for _, pkg := range packagesMap {
		packages = append(packages, pkg)
	}

	return packages, nil
}