Esempio 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
}
Esempio n. 2
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
}
Esempio n. 3
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
}
Esempio n. 4
0
File: rpm.go Progetto: kinvolk/clair
// Detect detects packages using var/lib/rpm/Packages from the input data
func (detector *RpmPackagesDetector) Detect(data map[string][]byte) ([]*database.Package, error) {
	f, hasFile := data["var/lib/rpm/Packages"]
	if !hasFile {
		return []*database.Package{}, nil
	}

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

	// 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.Package{}, 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.Package{}, 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.Package{}, 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.Package{Name: line[0], Version: version}
		packagesMap[pkg.Key()] = pkg
	}

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

	return packages, nil
}