mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
Merge pull request #257 from anchore/enhance-deb-support
Enhance dpkg support
This commit is contained in:
commit
2c82c7c0f0
@ -10,6 +10,19 @@
|
|||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"licenses": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"locations": {
|
"locations": {
|
||||||
"items": {
|
"items": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
@ -53,6 +66,11 @@
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
"items": {
|
"items": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@ -102,6 +120,8 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"gitCommitOfApkPort": {
|
"gitCommitOfApkPort": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -307,6 +327,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"foundBy",
|
"foundBy",
|
||||||
|
"licenses",
|
||||||
"locations",
|
"locations",
|
||||||
"name",
|
"name",
|
||||||
"type",
|
"type",
|
||||||
|
|||||||
@ -4,14 +4,193 @@ Package dpkg provides a concrete Cataloger implementation for Debian package DB
|
|||||||
package deb
|
package deb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/scope"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dpkgStatusGlob = "**/var/lib/dpkg/status"
|
||||||
|
md5sumsExt = ".md5sums"
|
||||||
|
docsPath = "/usr/share/doc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cataloger struct{}
|
||||||
|
|
||||||
// NewDpkgdbCataloger returns a new Deb package cataloger object.
|
// NewDpkgdbCataloger returns a new Deb package cataloger object.
|
||||||
func NewDpkgdbCataloger() *common.GenericCataloger {
|
func NewDpkgdbCataloger() *Cataloger {
|
||||||
globParsers := map[string]common.ParserFn{
|
return &Cataloger{}
|
||||||
"**/var/lib/dpkg/status": parseDpkgStatus,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return common.NewGenericCataloger(nil, globParsers, "dpkgdb-cataloger")
|
// Name returns a string that uniquely describes a cataloger
|
||||||
|
func (c *Cataloger) Name() string {
|
||||||
|
return "dpkgdb-cataloger"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing dpkg support files.
|
||||||
|
func (c *Cataloger) Catalog(resolver scope.Resolver) ([]pkg.Package, error) {
|
||||||
|
dbFileMatches, err := resolver.FilesByGlob(dpkgStatusGlob)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to find dpkg status files's by glob: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkgs []pkg.Package
|
||||||
|
for _, dbRef := range dbFileMatches {
|
||||||
|
dbContents, err := resolver.FileContentsByRef(dbRef)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgs, err = parseDpkgStatus(strings.NewReader(dbContents))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to catalog dpkg package=%+v: %w", dbRef.Path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
md5ContentsByName, md5RefsByName, err := fetchMd5Contents(resolver, dbRef, pkgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to find dpkg md5 contents: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
copyrightContentsByName, copyrightRefsByName, err := fetchCopyrightContents(resolver, dbRef, pkgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to find dpkg copyright contents: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range pkgs {
|
||||||
|
p := &pkgs[i]
|
||||||
|
p.FoundBy = c.Name()
|
||||||
|
p.Source = []file.Reference{dbRef}
|
||||||
|
|
||||||
|
if md5Reader, ok := md5ContentsByName[md5Key(*p)]; ok {
|
||||||
|
// attach the file list
|
||||||
|
metadata := p.Metadata.(pkg.DpkgMetadata)
|
||||||
|
metadata.Files = parseDpkgMD5Info(md5Reader)
|
||||||
|
p.Metadata = metadata
|
||||||
|
|
||||||
|
// keep a record of the file where this was discovered
|
||||||
|
if ref, ok := md5RefsByName[md5Key(*p)]; ok {
|
||||||
|
p.Source = append(p.Source, ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copyrightReader, ok := copyrightContentsByName[p.Name]
|
||||||
|
if ok {
|
||||||
|
// attach the licenses
|
||||||
|
p.Licenses = parseLicensesFromCopyright(copyrightReader)
|
||||||
|
|
||||||
|
// keep a record of the file where this was discovered
|
||||||
|
if ref, ok := copyrightRefsByName[p.Name]; ok {
|
||||||
|
p.Source = append(p.Source, ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchMd5Contents(resolver scope.Resolver, dbRef file.Reference, pkgs []pkg.Package) (map[string]io.Reader, map[string]file.Reference, error) {
|
||||||
|
// fetch all MD5 file contents. This approach is more efficient than fetching each MD5 file one at a time
|
||||||
|
|
||||||
|
var md5FileMatches []file.Reference
|
||||||
|
var nameByRef = make(map[file.Reference]string)
|
||||||
|
parentPath, err := dbRef.Path.ParentPath()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to find parent of path=%+v: %w", dbRef.Path, err)
|
||||||
|
}
|
||||||
|
for _, p := range pkgs {
|
||||||
|
// look for /var/lib/dpkg/info/NAME:ARCH.md5sums
|
||||||
|
name := md5Key(p)
|
||||||
|
md5sumPath := path.Join(string(parentPath), "info", name+md5sumsExt)
|
||||||
|
md5SumRef, err := resolver.RelativeFileByPath(dbRef, md5sumPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to find relative md5sum from path=%+v: %w", dbRef.Path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if md5SumRef == nil {
|
||||||
|
// the most specific key did not work, fallback to just the name
|
||||||
|
// look for /var/lib/dpkg/info/NAME.md5sums
|
||||||
|
name := p.Name
|
||||||
|
md5sumPath := path.Join(string(parentPath), "info", name+md5sumsExt)
|
||||||
|
md5SumRef, err = resolver.RelativeFileByPath(dbRef, md5sumPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to find relative md5sum from path=%+v: %w", dbRef.Path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we should have at least one reference
|
||||||
|
if md5SumRef != nil {
|
||||||
|
md5FileMatches = append(md5FileMatches, *md5SumRef)
|
||||||
|
nameByRef[*md5SumRef] = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the md5 contents
|
||||||
|
md5ContentsByRef, err := resolver.MultipleFileContentsByRef(md5FileMatches...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// organize content results and refs by a combination of name and architecture
|
||||||
|
var contentsByName = make(map[string]io.Reader)
|
||||||
|
var refsByName = make(map[string]file.Reference)
|
||||||
|
for ref, contents := range md5ContentsByRef {
|
||||||
|
name := nameByRef[ref]
|
||||||
|
contentsByName[name] = strings.NewReader(contents)
|
||||||
|
refsByName[name] = ref
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentsByName, refsByName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchCopyrightContents(resolver scope.Resolver, dbRef file.Reference, pkgs []pkg.Package) (map[string]io.Reader, map[string]file.Reference, error) {
|
||||||
|
// fetch all copyright file contents. This approach is more efficient than fetching each copyright file one at a time
|
||||||
|
|
||||||
|
var copyrightFileMatches []file.Reference
|
||||||
|
var nameByRef = make(map[file.Reference]string)
|
||||||
|
for _, p := range pkgs {
|
||||||
|
// look for /usr/share/docs/NAME/copyright files
|
||||||
|
name := p.Name
|
||||||
|
copyrightPath := path.Join(docsPath, name, "copyright")
|
||||||
|
copyrightRef, err := resolver.RelativeFileByPath(dbRef, copyrightPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to find relative copyright from path=%+v: %w", dbRef.Path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// we may not have a copyright file for each package, ignore missing files
|
||||||
|
if copyrightRef != nil {
|
||||||
|
copyrightFileMatches = append(copyrightFileMatches, *copyrightRef)
|
||||||
|
nameByRef[*copyrightRef] = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the copyright contents
|
||||||
|
copyrightContentsByRef, err := resolver.MultipleFileContentsByRef(copyrightFileMatches...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// organize content results and refs by package name
|
||||||
|
var contentsByName = make(map[string]io.Reader)
|
||||||
|
var refsByName = make(map[string]file.Reference)
|
||||||
|
for ref, contents := range copyrightContentsByRef {
|
||||||
|
name := nameByRef[ref]
|
||||||
|
contentsByName[name] = strings.NewReader(contents)
|
||||||
|
refsByName[name] = ref
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentsByName, refsByName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func md5Key(p pkg.Package) string {
|
||||||
|
metadata := p.Metadata.(pkg.DpkgMetadata)
|
||||||
|
|
||||||
|
contentKey := p.Name
|
||||||
|
if metadata.Architecture != "" && metadata.Architecture != "all" {
|
||||||
|
contentKey = contentKey + ":" + metadata.Architecture
|
||||||
|
}
|
||||||
|
return contentKey
|
||||||
}
|
}
|
||||||
|
|||||||
99
syft/cataloger/deb/cataloger_test.go
Normal file
99
syft/cataloger/deb/cataloger_test.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package deb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/scope"
|
||||||
|
"github.com/go-test/deep"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDpkgCataloger(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
sources map[string][]string
|
||||||
|
expected []pkg.Package
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "go-case",
|
||||||
|
sources: map[string][]string{
|
||||||
|
"libpam-runtime": {"/var/lib/dpkg/status", "/var/lib/dpkg/info/libpam-runtime.md5sums", "/usr/share/doc/libpam-runtime/copyright"},
|
||||||
|
},
|
||||||
|
expected: []pkg.Package{
|
||||||
|
{
|
||||||
|
Name: "libpam-runtime",
|
||||||
|
Version: "1.1.8-3.6",
|
||||||
|
FoundBy: "dpkgdb-cataloger",
|
||||||
|
Licenses: []string{"GPL-2", "LGPL-2.1"},
|
||||||
|
Type: pkg.DebPkg,
|
||||||
|
MetadataType: pkg.DpkgMetadataType,
|
||||||
|
Metadata: pkg.DpkgMetadata{
|
||||||
|
Package: "libpam-runtime",
|
||||||
|
Source: "pam",
|
||||||
|
Version: "1.1.8-3.6",
|
||||||
|
Architecture: "all",
|
||||||
|
Maintainer: "Steve Langasek <vorlon@debian.org>",
|
||||||
|
InstalledSize: 1016,
|
||||||
|
Files: []pkg.DpkgFileRecord{
|
||||||
|
{Path: "/lib/x86_64-linux-gnu/libz.so.1.2.11", MD5: "55f905631797551d4d936a34c7e73474"},
|
||||||
|
{Path: "/usr/share/doc/zlib1g/changelog.Debian.gz", MD5: "cede84bda30d2380217f97753c8ccf3a"},
|
||||||
|
{Path: "/usr/share/doc/zlib1g/changelog.gz", MD5: "f3c9dafa6da7992c47328b4464f6d122"},
|
||||||
|
{Path: "/usr/share/doc/zlib1g/copyright", MD5: "a4fae96070439a5209a62ae5b8017ab2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
img, cleanup := imagetest.GetFixtureImage(t, "docker-archive", "image-dpkg")
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
s, err := scope.NewScopeFromImage(img, scope.AllLayersScope)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := NewDpkgdbCataloger()
|
||||||
|
|
||||||
|
actual, err := c.Catalog(s.Resolver)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to catalog: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(actual) != len(test.expected) {
|
||||||
|
for _, a := range actual {
|
||||||
|
t.Logf(" %+v", a)
|
||||||
|
}
|
||||||
|
t.Fatalf("unexpected package count: %d!=%d", len(actual), len(test.expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
// test sources...
|
||||||
|
for idx := range actual {
|
||||||
|
a := &actual[idx]
|
||||||
|
// we will test the sources separately
|
||||||
|
var sourcesList = make([]string, len(a.Source))
|
||||||
|
for i, s := range a.Source {
|
||||||
|
sourcesList[i] = string(s.Path)
|
||||||
|
}
|
||||||
|
a.Source = nil
|
||||||
|
|
||||||
|
for _, d := range deep.Equal(sourcesList, test.sources[a.Name]) {
|
||||||
|
t.Errorf("diff: %+v", d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test remaining fields...
|
||||||
|
for _, d := range deep.Equal(actual, test.expected) {
|
||||||
|
t.Errorf("diff: %+v", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
38
syft/cataloger/deb/parse_copyright.go
Normal file
38
syft/cataloger/deb/parse_copyright.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package deb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For more information see: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/#license-syntax
|
||||||
|
|
||||||
|
func parseLicensesFromCopyright(reader io.Reader) []string {
|
||||||
|
findings := internal.NewStringSet()
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
if strings.HasPrefix(line, "License:") {
|
||||||
|
candidate := strings.Replace(line, "License:", "", 1)
|
||||||
|
candidate = strings.TrimSpace(candidate)
|
||||||
|
if strings.Contains(candidate, " or ") || strings.Contains(candidate, " and ") {
|
||||||
|
// this is a multi-license summary, ignore this as other recurrent license lines should cover this
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if candidate != "" && strings.ToLower(candidate) != "none" {
|
||||||
|
findings.Add(candidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results := findings.ToSlice()
|
||||||
|
|
||||||
|
sort.Strings(results)
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
58
syft/cataloger/deb/parse_copyright_test.go
Normal file
58
syft/cataloger/deb/parse_copyright_test.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package deb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-test/deep"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseLicensesFromCopyright(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
fixture string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/copyright/trilicense",
|
||||||
|
expected: []string{"GPL-2", "LGPL-2.1", "MPL-1.1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/copyright/liblzma5",
|
||||||
|
expected: []string{"Autoconf", "GPL-2", "GPL-2+", "LGPL-2.1+", "PD", "PD-debian", "config-h", "noderivs", "permissive-fsf", "permissive-nowarranty", "probably-PD"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/copyright/libaudit-common",
|
||||||
|
expected: []string{"GPL-2", "LGPL-2.1"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.fixture, func(t *testing.T) {
|
||||||
|
file, err := os.Open(test.fixture)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to read: ", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("closing file failed:", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
actual := parseLicensesFromCopyright(file)
|
||||||
|
|
||||||
|
if len(actual) != len(test.expected) {
|
||||||
|
for _, a := range actual {
|
||||||
|
t.Logf(" %+v", a)
|
||||||
|
}
|
||||||
|
t.Fatalf("unexpected package count: %d!=%d", len(actual), len(test.expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
diffs := deep.Equal(actual, test.expected)
|
||||||
|
for _, d := range diffs {
|
||||||
|
t.Errorf("diff: %+v", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
30
syft/cataloger/deb/parse_dpkg_info_files.go
Normal file
30
syft/cataloger/deb/parse_dpkg_info_files.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package deb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseDpkgMD5Info(reader io.Reader) []pkg.DpkgFileRecord {
|
||||||
|
var findings []pkg.DpkgFileRecord
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
fields := strings.SplitN(line, " ", 2)
|
||||||
|
if len(fields) == 2 {
|
||||||
|
path := strings.TrimSpace(fields[1])
|
||||||
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
path = "/" + path
|
||||||
|
}
|
||||||
|
findings = append(findings, pkg.DpkgFileRecord{
|
||||||
|
Path: path,
|
||||||
|
MD5: strings.TrimSpace(fields[0]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return findings
|
||||||
|
}
|
||||||
57
syft/cataloger/deb/parse_dpkg_info_files_test.go
Normal file
57
syft/cataloger/deb/parse_dpkg_info_files_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package deb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-test/deep"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMD5SumInfoParsing(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
fixture string
|
||||||
|
expected []pkg.DpkgFileRecord
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/info/zlib1g.md5sums",
|
||||||
|
expected: []pkg.DpkgFileRecord{
|
||||||
|
{Path: "/lib/x86_64-linux-gnu/libz.so.1.2.11", MD5: "55f905631797551d4d936a34c7e73474"},
|
||||||
|
{Path: "/usr/share/doc/zlib1g/changelog.Debian.gz", MD5: "cede84bda30d2380217f97753c8ccf3a"},
|
||||||
|
{Path: "/usr/share/doc/zlib1g/changelog.gz", MD5: "f3c9dafa6da7992c47328b4464f6d122"},
|
||||||
|
{Path: "/usr/share/doc/zlib1g/copyright", MD5: "a4fae96070439a5209a62ae5b8017ab2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.fixture, func(t *testing.T) {
|
||||||
|
file, err := os.Open(test.fixture)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to read: ", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("closing file failed:", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
actual := parseDpkgMD5Info(file)
|
||||||
|
|
||||||
|
if len(actual) != len(test.expected) {
|
||||||
|
for _, a := range actual {
|
||||||
|
t.Logf(" %+v", a)
|
||||||
|
}
|
||||||
|
t.Fatalf("unexpected package count: %d!=%d", len(actual), len(test.expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
diffs := deep.Equal(actual, test.expected)
|
||||||
|
for _, d := range diffs {
|
||||||
|
t.Errorf("diff: %+v", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,33 +2,35 @@ package deb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// integrity check
|
|
||||||
var _ common.ParserFn = parseDpkgStatus
|
|
||||||
|
|
||||||
var errEndOfPackages = fmt.Errorf("no more packages to read")
|
var errEndOfPackages = fmt.Errorf("no more packages to read")
|
||||||
|
|
||||||
// parseDpkgStatus is a parser function for Debian DB status contents, returning all Debian packages listed.
|
// parseDpkgStatus is a parser function for Debian DB status contents, returning all Debian packages listed.
|
||||||
func parseDpkgStatus(_ string, reader io.Reader) ([]pkg.Package, error) {
|
func parseDpkgStatus(reader io.Reader) ([]pkg.Package, error) {
|
||||||
buffedReader := bufio.NewReader(reader)
|
buffedReader := bufio.NewReader(reader)
|
||||||
var packages = make([]pkg.Package, 0)
|
var packages = make([]pkg.Package, 0)
|
||||||
|
|
||||||
for {
|
continueProcessing := true
|
||||||
|
for continueProcessing {
|
||||||
entry, err := parseDpkgStatusEntry(buffedReader)
|
entry, err := parseDpkgStatusEntry(buffedReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errEndOfPackages {
|
if errors.Is(err, errEndOfPackages) {
|
||||||
break
|
continueProcessing = false
|
||||||
}
|
} else {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.Package != "" {
|
||||||
packages = append(packages, pkg.Package{
|
packages = append(packages, pkg.Package{
|
||||||
Name: entry.Package,
|
Name: entry.Package,
|
||||||
Version: entry.Version,
|
Version: entry.Version,
|
||||||
@ -37,20 +39,23 @@ func parseDpkgStatus(_ string, reader io.Reader) ([]pkg.Package, error) {
|
|||||||
Metadata: entry,
|
Metadata: entry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return packages, nil
|
return packages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseDpkgStatusEntry returns an individual Dpkg entry, or returns errEndOfPackages if there are no more packages to parse from the reader.
|
// parseDpkgStatusEntry returns an individual Dpkg entry, or returns errEndOfPackages if there are no more packages to parse from the reader.
|
||||||
func parseDpkgStatusEntry(reader *bufio.Reader) (entry pkg.DpkgMetadata, err error) {
|
func parseDpkgStatusEntry(reader *bufio.Reader) (entry pkg.DpkgMetadata, err error) {
|
||||||
dpkgFields := make(map[string]string)
|
dpkgFields := make(map[string]interface{})
|
||||||
|
var retErr error
|
||||||
var key string
|
var key string
|
||||||
|
|
||||||
for {
|
for {
|
||||||
line, err := reader.ReadString('\n')
|
line, err := reader.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return pkg.DpkgMetadata{}, errEndOfPackages
|
retErr = errEndOfPackages
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return pkg.DpkgMetadata{}, err
|
return pkg.DpkgMetadata{}, err
|
||||||
}
|
}
|
||||||
@ -82,18 +87,16 @@ func parseDpkgStatusEntry(reader *bufio.Reader) (entry pkg.DpkgMetadata, err err
|
|||||||
dpkgFields[key] = val
|
dpkgFields[key] = val
|
||||||
default:
|
default:
|
||||||
// parse a new key
|
// parse a new key
|
||||||
if i := strings.Index(line, ":"); i > 0 {
|
var val interface{}
|
||||||
key = strings.TrimSpace(line[0:i])
|
key, val, err = handleNewKeyValue(line)
|
||||||
val := strings.TrimSpace(line[i+1:])
|
if err != nil {
|
||||||
|
return pkg.DpkgMetadata{}, err
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := dpkgFields[key]; ok {
|
if _, ok := dpkgFields[key]; ok {
|
||||||
return pkg.DpkgMetadata{}, fmt.Errorf("duplicate key discovered: %s", key)
|
return pkg.DpkgMetadata{}, fmt.Errorf("duplicate key discovered: %s", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
dpkgFields[key] = val
|
dpkgFields[key] = val
|
||||||
} else {
|
|
||||||
return pkg.DpkgMetadata{}, fmt.Errorf("cannot parse field from line: '%s'", line)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,5 +105,29 @@ func parseDpkgStatusEntry(reader *bufio.Reader) (entry pkg.DpkgMetadata, err err
|
|||||||
return pkg.DpkgMetadata{}, err
|
return pkg.DpkgMetadata{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry, nil
|
return entry, retErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleNewKeyValue parse a new key-value pair from the given unprocessed line
|
||||||
|
func handleNewKeyValue(line string) (string, interface{}, error) {
|
||||||
|
if i := strings.Index(line, ":"); i > 0 {
|
||||||
|
var key = strings.TrimSpace(line[0:i])
|
||||||
|
// mapstruct cant handle "-"
|
||||||
|
key = strings.ReplaceAll(key, "-", "")
|
||||||
|
val := strings.TrimSpace(line[i+1:])
|
||||||
|
|
||||||
|
// further processing of values based on the key that was discovered
|
||||||
|
switch key {
|
||||||
|
case "InstalledSize":
|
||||||
|
numVal, err := strconv.Atoi(val)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, fmt.Errorf("bad installed-size value=%q: %w", val, err)
|
||||||
|
}
|
||||||
|
return key, numVal, nil
|
||||||
|
default:
|
||||||
|
return key, val, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil, fmt.Errorf("cannot parse field from line: '%s'", line)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,13 +28,15 @@ func TestSinglePackage(t *testing.T) {
|
|||||||
Source: "apt-dev",
|
Source: "apt-dev",
|
||||||
Version: "1.8.2",
|
Version: "1.8.2",
|
||||||
Architecture: "amd64",
|
Architecture: "amd64",
|
||||||
|
InstalledSize: 4064,
|
||||||
|
Maintainer: "APT Development Team <deity@lists.debian.org>",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
file, err := os.Open("test-fixtures/single")
|
file, err := os.Open("test-fixtures/status/single")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read test_fixtures/single: ", err)
|
t.Fatal("Unable to read test_fixtures/single: ", err)
|
||||||
}
|
}
|
||||||
@ -70,11 +72,15 @@ func TestMultiplePackages(t *testing.T) {
|
|||||||
Version: "2020a-0+deb10u1",
|
Version: "2020a-0+deb10u1",
|
||||||
Source: "tzdata-dev",
|
Source: "tzdata-dev",
|
||||||
Architecture: "all",
|
Architecture: "all",
|
||||||
|
InstalledSize: 3036,
|
||||||
|
Maintainer: "GNU Libc Maintainers <debian-glibc@lists.debian.org>",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Package: "util-linux",
|
Package: "util-linux",
|
||||||
Version: "2.33.1-0.1",
|
Version: "2.33.1-0.1",
|
||||||
Architecture: "amd64",
|
Architecture: "amd64",
|
||||||
|
InstalledSize: 4327,
|
||||||
|
Maintainer: "LaMont Jones <lamont@debian.org>",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -82,7 +88,7 @@ func TestMultiplePackages(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
file, err := os.Open("test-fixtures/multiple")
|
file, err := os.Open("test-fixtures/status/multiple")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read: ", err)
|
t.Fatal("Unable to read: ", err)
|
||||||
}
|
}
|
||||||
@ -93,7 +99,7 @@ func TestMultiplePackages(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pkgs, err := parseDpkgStatus(file.Name(), file)
|
pkgs, err := parseDpkgStatus(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("Unable to read file contents: ", err)
|
t.Fatal("Unable to read file contents: ", err)
|
||||||
}
|
}
|
||||||
|
|||||||
43
syft/cataloger/deb/test-fixtures/copyright/libaudit-common
Normal file
43
syft/cataloger/deb/test-fixtures/copyright/libaudit-common
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: auditd
|
||||||
|
Source: https://people.redhat.com/sgrubb/audit/
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2012-2016 Steve Grubb <sgrubb@redhat.com>
|
||||||
|
2006-2012 Rik Faith
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
Files: src/libev/*
|
||||||
|
Copyright: 2007-2009 Marc Alexamder Lehmann
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
Files: lib/*
|
||||||
|
Copyright: 2005-2008 Steve Grubb <sgrubb@redhat.com>
|
||||||
|
License: LGPL-2.1
|
||||||
|
The audit daemon's library libaudit.* is released under LGPL
|
||||||
|
so that it may be linked with 3rd party software.
|
||||||
|
.
|
||||||
|
On Debian systems, refer to /usr/share/common-licenses/LGPL-2.1
|
||||||
|
for the complete text of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2007-2011 Philipp Matthias Hahn <pmhahn@debian.org>
|
||||||
|
2012-2016 Laurent Bigonville <bigon@debian.org>
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
License: GPL-2
|
||||||
|
This package is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License version 2,
|
||||||
|
as published by the Free Software Foundation.
|
||||||
|
.
|
||||||
|
This package is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this package; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License can be found in `/usr/share/common-licenses/GPL-1'.
|
||||||
383
syft/cataloger/deb/test-fixtures/copyright/liblzma5
Normal file
383
syft/cataloger/deb/test-fixtures/copyright/liblzma5
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: XZ Utils
|
||||||
|
Upstream-Contact:
|
||||||
|
Lasse Collin <lasse.collin@tukaani.org>
|
||||||
|
http://tukaani.org/xz/lists.html
|
||||||
|
Source:
|
||||||
|
http://tukaani.org/xz
|
||||||
|
http://git.tukaani.org/xz.git
|
||||||
|
Comment:
|
||||||
|
XZ Utils is developed and maintained upstream by Lasse Collin. Major
|
||||||
|
portions are based on code by other authors; see AUTHORS for details.
|
||||||
|
Most of the source has been put into the public domain, but some files
|
||||||
|
have not (details below).
|
||||||
|
.
|
||||||
|
This file describes the source package. The binary packages contain
|
||||||
|
some files derived from other works: for example, images in the API
|
||||||
|
documentation come from Doxygen.
|
||||||
|
License:
|
||||||
|
Different licenses apply to different files in this package. Here
|
||||||
|
is a rough summary of which licenses apply to which parts of this
|
||||||
|
package (but check the individual files to be sure!):
|
||||||
|
.
|
||||||
|
- liblzma is in the public domain.
|
||||||
|
.
|
||||||
|
- xz, xzdec, and lzmadec command line tools are in the public
|
||||||
|
domain unless GNU getopt_long had to be compiled and linked
|
||||||
|
in from the lib directory. The getopt_long code is under
|
||||||
|
GNU LGPLv2.1+.
|
||||||
|
.
|
||||||
|
- The scripts to grep, diff, and view compressed files have been
|
||||||
|
adapted from gzip. These scripts and their documentation are
|
||||||
|
under GNU GPLv2+.
|
||||||
|
.
|
||||||
|
- All the documentation in the doc directory and most of the
|
||||||
|
XZ Utils specific documentation files in other directories
|
||||||
|
are in the public domain.
|
||||||
|
.
|
||||||
|
- Translated messages are in the public domain.
|
||||||
|
.
|
||||||
|
- The build system contains public domain files, and files that
|
||||||
|
are under GNU GPLv2+ or GNU GPLv3+. None of these files end up
|
||||||
|
in the binaries being built.
|
||||||
|
.
|
||||||
|
- Test files and test code in the tests directory, and debugging
|
||||||
|
utilities in the debug directory are in the public domain.
|
||||||
|
.
|
||||||
|
- The extra directory may contain public domain files, and files
|
||||||
|
that are under various free software licenses.
|
||||||
|
.
|
||||||
|
You can do whatever you want with the files that have been put into
|
||||||
|
the public domain. If you find public domain legally problematic,
|
||||||
|
take the previous sentence as a license grant. If you still find
|
||||||
|
the lack of copyright legally problematic, you have too many
|
||||||
|
lawyers.
|
||||||
|
.
|
||||||
|
As usual, this software is provided "as is", without any warranty.
|
||||||
|
.
|
||||||
|
If you copy significant amounts of public domain code from XZ Utils
|
||||||
|
into your project, acknowledging this somewhere in your software is
|
||||||
|
polite (especially if it is proprietary, non-free software), but
|
||||||
|
naturally it is not legally required. Here is an example of a good
|
||||||
|
notice to put into "about box" or into documentation:
|
||||||
|
.
|
||||||
|
This software includes code from XZ Utils <http://tukaani.org/xz/>.
|
||||||
|
.
|
||||||
|
The following license texts are included in the following files:
|
||||||
|
- COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
|
||||||
|
- COPYING.GPLv2: GNU General Public License version 2
|
||||||
|
- COPYING.GPLv3: GNU General Public License version 3
|
||||||
|
.
|
||||||
|
Note that the toolchain (compiler, linker etc.) may add some code
|
||||||
|
pieces that are copyrighted. Thus, it is possible that e.g. liblzma
|
||||||
|
binary wouldn't actually be in the public domain in its entirety
|
||||||
|
even though it contains no copyrighted code from the XZ Utils source
|
||||||
|
package.
|
||||||
|
.
|
||||||
|
If you have questions, don't hesitate to ask the author(s) for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2006-2012, Lasse Collin
|
||||||
|
1999-2008, Igor Pavlov
|
||||||
|
2006, Ville Koskinen
|
||||||
|
1998, Steve Reid
|
||||||
|
2000, Wei Dai
|
||||||
|
2003, Kevin Springle
|
||||||
|
2009, Jonathan Nieder
|
||||||
|
2010, Anders F Björklund
|
||||||
|
License: PD
|
||||||
|
This file has been put in the public domain.
|
||||||
|
You can do whatever you want with this file.
|
||||||
|
Comment:
|
||||||
|
From: Lasse Collin <lasse.collin@tukaani.org>
|
||||||
|
To: Jonathan Nieder <jrnieder@gmail.com>
|
||||||
|
Subject: Re: XZ utils for Debian
|
||||||
|
Date: Sun, 19 Jul 2009 13:28:23 +0300
|
||||||
|
Message-Id: <200907191328.23816.lasse.collin@tukaani.org>
|
||||||
|
.
|
||||||
|
[...]
|
||||||
|
.
|
||||||
|
> AUTHORS, ChangeLog, COPYING, README, THANKS, TODO,
|
||||||
|
> dos/README, windows/README
|
||||||
|
.
|
||||||
|
COPYING says that most docs are in the public domain. Maybe that's not
|
||||||
|
clear enough, but on the other hand it looks a bit stupid to put
|
||||||
|
copyright information in tiny and relatively small docs like README.
|
||||||
|
.
|
||||||
|
I don't dare to say that _all_ XZ Utils specific docs are in the public
|
||||||
|
domain unless otherwise mentioned in the file. I'm including PDF files
|
||||||
|
generated by groff + ps2pdf, and some day I might include Doxygen-
|
||||||
|
generated HTML docs too. Those don't include any copyright notices, but
|
||||||
|
it seems likely that groff + ps2pdf or at least Doxygen put some
|
||||||
|
copyrighted content into the generated files.
|
||||||
|
|
||||||
|
Files: INSTALL NEWS PACKAGERS
|
||||||
|
windows/README-Windows.txt
|
||||||
|
windows/INSTALL-Windows.txt
|
||||||
|
Copyright: 2009-2010, Lasse Collin
|
||||||
|
License: probably-PD
|
||||||
|
See the note on AUTHORS, README, and so on above.
|
||||||
|
|
||||||
|
Files: src/scripts/* lib/* extra/scanlzma/scanlzma.c
|
||||||
|
Copyright: © 1993, Jean-loup Gailly
|
||||||
|
© 1989-1994, 1996-1999, 2001-2007, Free Software Foundation, Inc.
|
||||||
|
© 2006 Timo Lindfors
|
||||||
|
2005, Charles Levert
|
||||||
|
2005, 2009, Lasse Collin
|
||||||
|
2009, Andrew Dudman
|
||||||
|
Other-Authors: Paul Eggert, Ulrich Drepper
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
Files: src/scripts/Makefile.am src/scripts/xzless.1
|
||||||
|
Copyright: 2009, Andrew Dudman
|
||||||
|
2009, Lasse Collin
|
||||||
|
License: PD
|
||||||
|
This file has been put in the public domain.
|
||||||
|
You can do whatever you want with this file.
|
||||||
|
|
||||||
|
Files: doc/examples/xz_pipe_comp.c doc/examples/xz_pipe_decomp.c
|
||||||
|
Copyright: 2010, Daniel Mealha Cabrita
|
||||||
|
License: PD
|
||||||
|
Not copyrighted -- provided to the public domain.
|
||||||
|
|
||||||
|
Files: lib/getopt.c lib/getopt1.c lib/getopt.in.h
|
||||||
|
Copyright: © 1987-2007 Free Software Foundation, Inc.
|
||||||
|
Other-Authors: Ulrich Drepper
|
||||||
|
License: LGPL-2.1+
|
||||||
|
|
||||||
|
Files: m4/getopt.m4 m4/posix-shell.m4
|
||||||
|
Copyright: © 2002-2006, 2008 Free Software Foundation, Inc.
|
||||||
|
© 2007-2008 Free Software Foundation, Inc.
|
||||||
|
Other-Authors: Bruno Haible, Paul Eggert
|
||||||
|
License: permissive-fsf
|
||||||
|
|
||||||
|
Files: m4/acx_pthread.m4
|
||||||
|
Copyright: © 2008, Steven G. Johnson <stevenj@alum.mit.edu>
|
||||||
|
License: Autoconf
|
||||||
|
|
||||||
|
Files: Doxyfile.in
|
||||||
|
Copyright: © 1997-2007 by Dimitri van Heesch
|
||||||
|
Origin: Doxygen 1.4.7
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
Files: src/liblzma/check/crc32_table_?e.h
|
||||||
|
src/liblzma/check/crc64_table_?e.h
|
||||||
|
src/liblzma/lzma/fastpos_table.c
|
||||||
|
src/liblzma/rangecoder/price_table.c
|
||||||
|
Copyright: none, automatically generated data
|
||||||
|
Generated-With:
|
||||||
|
src/liblzma/check/crc32_tablegen.c
|
||||||
|
src/liblzma/check/crc64_tablegen.c
|
||||||
|
src/liblzma/lzma/fastpos_tablegen.c
|
||||||
|
src/liblzma/rangecoder/price_tablegen.c
|
||||||
|
License: none
|
||||||
|
No copyright to license.
|
||||||
|
|
||||||
|
Files: .gitignore m4/.gitignore po/.gitignore po/LINGUAS po/POTFILES.in
|
||||||
|
Copyright: none; these are just short lists.
|
||||||
|
License: none
|
||||||
|
No copyright to license.
|
||||||
|
|
||||||
|
Files: tests/compress_prepared_bcj_*
|
||||||
|
Copyright: 2008-2009, Lasse Collin
|
||||||
|
Source-Code: tests/bcj_test.c
|
||||||
|
License: PD
|
||||||
|
This file has been put into the public domain.
|
||||||
|
You can do whatever you want with this file.
|
||||||
|
Comment:
|
||||||
|
changelog.gz (commit 975d8fd) explains:
|
||||||
|
.
|
||||||
|
Recreated the BCJ test files for x86 and SPARC. The old files
|
||||||
|
were linked with crt*.o, which are copyrighted, and thus the
|
||||||
|
old test files were not in the public domain as a whole. They
|
||||||
|
are freely distributable though, but it is better to be careful
|
||||||
|
and avoid including any copyrighted pieces in the test files.
|
||||||
|
The new files are just compiled and assembled object files,
|
||||||
|
and thus don't contain any copyrighted code.
|
||||||
|
|
||||||
|
Files: po/cs.po po/de.po po/fr.po
|
||||||
|
Copyright: 2010, Marek Černocký
|
||||||
|
2010, Andre Noll
|
||||||
|
2011, Adrien Nader
|
||||||
|
License: PD
|
||||||
|
This file is put in the public domain.
|
||||||
|
|
||||||
|
Files: po/it.po po/pl.po
|
||||||
|
Copyright: 2009, 2010, Gruppo traduzione italiano di Ubuntu-it
|
||||||
|
2010, Lorenzo De Liso
|
||||||
|
2009, 2010, 2011, Milo Casagrande
|
||||||
|
2011, Jakub Bogusz
|
||||||
|
License: PD
|
||||||
|
This file is in the public domain
|
||||||
|
|
||||||
|
Files: INSTALL.generic
|
||||||
|
Copyright: © 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||||
|
2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||||
|
License: permissive-nowarranty
|
||||||
|
|
||||||
|
Files: dos/config.h
|
||||||
|
Copyright: © 1992, 1993, 1994, 1999, 2000, 2001, 2002, 2005
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
2007-2010, Lasse Collin
|
||||||
|
Other-Authors: Roland McGrath, Akim Demaille, Paul Eggert,
|
||||||
|
David Mackenzie, Bruno Haible, and many others.
|
||||||
|
Origin: configure.ac from XZ Utils,
|
||||||
|
visibility.m4 serial 1 (gettext-0.15),
|
||||||
|
Autoconf 2.52g
|
||||||
|
License: config-h
|
||||||
|
configure.ac:
|
||||||
|
.
|
||||||
|
# Author: Lasse Collin
|
||||||
|
#
|
||||||
|
# This file has been put into the public domain.
|
||||||
|
# You can do whatever you want with this file.
|
||||||
|
.
|
||||||
|
visibility.m4:
|
||||||
|
.
|
||||||
|
dnl Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
.
|
||||||
|
dnl From Bruno Haible.
|
||||||
|
.
|
||||||
|
comments from Autoconf 2.52g:
|
||||||
|
.
|
||||||
|
# Copyright 1992, 1993, 1994, 1999, 2000, 2001, 2002
|
||||||
|
# Free Software Foundation, Inc.
|
||||||
|
.
|
||||||
|
[...]
|
||||||
|
.
|
||||||
|
# As a special exception, the Free Software Foundation gives unlimited
|
||||||
|
# permission to copy, distribute and modify the configure scripts that
|
||||||
|
# are the output of Autoconf. You need not follow the terms of the GNU
|
||||||
|
# General Public License when using or distributing such scripts, even
|
||||||
|
# though portions of the text of Autoconf appear in them. The GNU
|
||||||
|
# General Public License (GPL) does govern all other use of the material
|
||||||
|
# that constitutes the Autoconf program.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General Public
|
||||||
|
License version 2 can be found in ‘/usr/share/common-licenses/GPL-2’.
|
||||||
|
dos/config.h was generated with autoheader, which tells Autoconf to
|
||||||
|
output a script to generate a config.h file and then runs it.
|
||||||
|
|
||||||
|
Files: po/Makevars
|
||||||
|
Origin: gettext-runtime/po/Makevars (gettext-0.12)
|
||||||
|
Copyright: © 2003 Free Software Foundation, Inc.
|
||||||
|
Authors: Bruno Haible
|
||||||
|
License: LGPL-2.1+
|
||||||
|
The gettext-runtime package is under the LGPL, see files intl/COPYING.LIB-2.0
|
||||||
|
and intl/COPYING.LIB-2.1.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of intl/COPYING.LIB-2.0 from
|
||||||
|
gettext-runtime 0.12 can be found in ‘/usr/share/common-licenses/LGPL-2’
|
||||||
|
and the text of intl/COPYING.LIB-2.1 can be found in
|
||||||
|
‘/usr/share/common-licenses/LGPL-2.1’.
|
||||||
|
.
|
||||||
|
po/Makevars consists mostly of helpful comments and does not contain a
|
||||||
|
copyright and license notice.
|
||||||
|
|
||||||
|
Files: COPYING.GPLv2 COPYING.GPLv3 COPYING.LGPLv2.1
|
||||||
|
Copyright: © 1989, 1991, 1999, 2007 Free Software Foundation, Inc.
|
||||||
|
License: noderivs
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2009-2012, Jonathan Nieder
|
||||||
|
License: PD-debian
|
||||||
|
The Debian packaging files are in the public domain.
|
||||||
|
You may freely use, modify, distribute, and relicense them.
|
||||||
|
|
||||||
|
License: LGPL-2.1+
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1, or (at your option)
|
||||||
|
any later version.
|
||||||
|
.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU Lesser General Public
|
||||||
|
License version 2.1 can be found in ‘/usr/share/common-licenses/LGPL-2.1’.
|
||||||
|
|
||||||
|
License: GPL-2
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation under the terms of the GNU General Public License is
|
||||||
|
hereby granted. No representations are made about the suitability of
|
||||||
|
this software for any purpose. It is provided "as is" without express
|
||||||
|
or implied warranty. See the GNU General Public License for more
|
||||||
|
details.
|
||||||
|
.
|
||||||
|
Documents produced by doxygen are derivative works derived from the
|
||||||
|
input used in their production; they are not affected by this license.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the version of the GNU General
|
||||||
|
Public License distributed with Doxygen can be found in
|
||||||
|
‘/usr/share/common-licenses/GPL-2’.
|
||||||
|
|
||||||
|
License: GPL-2+
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General Public License
|
||||||
|
version 2 can be found in ‘/usr/share/common-licenses/GPL-2’.
|
||||||
|
|
||||||
|
License: Autoconf
|
||||||
|
This program is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
.
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
As a special exception, the respective Autoconf Macro's copyright owner
|
||||||
|
gives unlimited permission to copy, distribute and modify the configure
|
||||||
|
scripts that are the output of Autoconf when processing the Macro. You
|
||||||
|
need not follow the terms of the GNU General Public License when using
|
||||||
|
or distributing such scripts, even though portions of the text of the
|
||||||
|
Macro appear in them. The GNU General Public License (GPL) does govern
|
||||||
|
all other use of the material that constitutes the Autoconf Macro.
|
||||||
|
.
|
||||||
|
This special exception to the GPL applies to versions of the Autoconf
|
||||||
|
Macro released by the Autoconf Archive. When you make and distribute a
|
||||||
|
modified version of the Autoconf Macro, you may extend this special
|
||||||
|
exception to the GPL to apply to your modified version as well.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General Public
|
||||||
|
License version 3 can be found in ‘/usr/share/common-licenses/GPL-3’.
|
||||||
|
|
||||||
|
License: permissive-fsf
|
||||||
|
This file is free software; the Free Software Foundation
|
||||||
|
gives unlimited permission to copy and/or distribute it,
|
||||||
|
with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
License: permissive-nowarranty
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. This file is offered as-is,
|
||||||
|
without warranty of any kind.
|
||||||
13
syft/cataloger/deb/test-fixtures/copyright/trilicense
Normal file
13
syft/cataloger/deb/test-fixtures/copyright/trilicense
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Files: src/js/editline/*
|
||||||
|
Copyright: 1993, John Doe
|
||||||
|
1993, Joe Average
|
||||||
|
License: MPL-1.1 or GPL-2 or LGPL-2.1
|
||||||
|
|
||||||
|
License: MPL-1.1
|
||||||
|
[LICENSE TEXT]
|
||||||
|
|
||||||
|
License: GPL-2
|
||||||
|
[LICENSE TEXT]
|
||||||
|
|
||||||
|
License: LGPL-2.1
|
||||||
|
[LICENSE TEXT]
|
||||||
2
syft/cataloger/deb/test-fixtures/image-dpkg/Dockerfile
Normal file
2
syft/cataloger/deb/test-fixtures/image-dpkg/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
FROM scratch
|
||||||
|
COPY . .
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: auditd
|
||||||
|
Source: https://people.redhat.com/sgrubb/audit/
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2012-2016 Steve Grubb <sgrubb@redhat.com>
|
||||||
|
2006-2012 Rik Faith
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
Files: src/libev/*
|
||||||
|
Copyright: 2007-2009 Marc Alexamder Lehmann
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
Files: lib/*
|
||||||
|
Copyright: 2005-2008 Steve Grubb <sgrubb@redhat.com>
|
||||||
|
License: LGPL-2.1
|
||||||
|
The audit daemon's library libaudit.* is released under LGPL
|
||||||
|
so that it may be linked with 3rd party software.
|
||||||
|
.
|
||||||
|
On Debian systems, refer to /usr/share/common-licenses/LGPL-2.1
|
||||||
|
for the complete text of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2007-2011 Philipp Matthias Hahn <pmhahn@debian.org>
|
||||||
|
2012-2016 Laurent Bigonville <bigon@debian.org>
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
License: GPL-2
|
||||||
|
This package is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License version 2,
|
||||||
|
as published by the Free Software Foundation.
|
||||||
|
.
|
||||||
|
This package is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this package; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License can be found in `/usr/share/common-licenses/GPL-1'.
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
55f905631797551d4d936a34c7e73474 lib/x86_64-linux-gnu/libz.so.1.2.11
|
||||||
|
cede84bda30d2380217f97753c8ccf3a usr/share/doc/zlib1g/changelog.Debian.gz
|
||||||
|
f3c9dafa6da7992c47328b4464f6d122 usr/share/doc/zlib1g/changelog.gz
|
||||||
|
a4fae96070439a5209a62ae5b8017ab2 usr/share/doc/zlib1g/copyright
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
Package: libpam-runtime
|
||||||
|
Status: install ok installed
|
||||||
|
Priority: required
|
||||||
|
Section: admin
|
||||||
|
Installed-Size: 1016
|
||||||
|
Maintainer: Steve Langasek <vorlon@debian.org>
|
||||||
|
Architecture: all
|
||||||
|
Multi-Arch: foreign
|
||||||
|
Source: pam
|
||||||
|
Version: 1.1.8-3.6
|
||||||
|
Replaces: libpam0g-dev, libpam0g-util
|
||||||
|
Depends: debconf (>= 0.5) | debconf-2.0, debconf (>= 1.5.19) | cdebconf, libpam-modules (>= 1.0.1-6)
|
||||||
|
Conflicts: libpam0g-util
|
||||||
|
Conffiles:
|
||||||
|
/etc/pam.conf 87fc76f18e98ee7d3848f6b81b3391e5
|
||||||
|
/etc/pam.d/other 31aa7f2181889ffb00b87df4126d1701
|
||||||
|
Description: Runtime support for the PAM library
|
||||||
|
Contains configuration files and directories required for
|
||||||
|
authentication to work on Debian systems. This package is required
|
||||||
|
on almost all installations.
|
||||||
|
Homepage: http://www.linux-pam.org/
|
||||||
4
syft/cataloger/deb/test-fixtures/info/zlib1g.md5sums
Normal file
4
syft/cataloger/deb/test-fixtures/info/zlib1g.md5sums
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
55f905631797551d4d936a34c7e73474 lib/x86_64-linux-gnu/libz.so.1.2.11
|
||||||
|
cede84bda30d2380217f97753c8ccf3a usr/share/doc/zlib1g/changelog.Debian.gz
|
||||||
|
f3c9dafa6da7992c47328b4464f6d122 usr/share/doc/zlib1g/changelog.gz
|
||||||
|
a4fae96070439a5209a62ae5b8017ab2 usr/share/doc/zlib1g/copyright
|
||||||
@ -12,7 +12,14 @@ type DpkgMetadata struct {
|
|||||||
Source string `mapstructure:"Source" json:"source"`
|
Source string `mapstructure:"Source" json:"source"`
|
||||||
Version string `mapstructure:"Version" json:"version"`
|
Version string `mapstructure:"Version" json:"version"`
|
||||||
Architecture string `mapstructure:"Architecture" json:"architecture"`
|
Architecture string `mapstructure:"Architecture" json:"architecture"`
|
||||||
// TODO: consider keeping the remaining values as an embedded map
|
Maintainer string `mapstructure:"Maintainer" json:"maintainer"`
|
||||||
|
InstalledSize int `mapstructure:"InstalledSize" json:"installedSize"`
|
||||||
|
Files []DpkgFileRecord `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DpkgFileRecord struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
MD5 string `json:"md5"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m DpkgMetadata) PackageURL(d distro.Distro) string {
|
func (m DpkgMetadata) PackageURL(d distro.Distro) string {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ type Artifact struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
FoundBy []string `json:"foundBy"`
|
FoundBy []string `json:"foundBy"`
|
||||||
Locations Locations `json:"locations,omitempty"`
|
Locations Locations `json:"locations,omitempty"`
|
||||||
|
Licenses []string `json:"licenses"`
|
||||||
Metadata interface{} `json:"metadata,omitempty"`
|
Metadata interface{} `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ func NewArtifact(p *pkg.Package, s scope.Scope) (Artifact, error) {
|
|||||||
Type: string(p.Type),
|
Type: string(p.Type),
|
||||||
FoundBy: []string{p.FoundBy},
|
FoundBy: []string{p.FoundBy},
|
||||||
Locations: locations,
|
Locations: locations,
|
||||||
|
Licenses: p.Licenses,
|
||||||
Metadata: p.Metadata,
|
Metadata: p.Metadata,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
],
|
],
|
||||||
"locations": [
|
"locations": [
|
||||||
"/some/path/pkg1"
|
"/some/path/pkg1"
|
||||||
]
|
],
|
||||||
|
"licenses": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
@ -20,7 +21,8 @@
|
|||||||
],
|
],
|
||||||
"locations": [
|
"locations": [
|
||||||
"/some/path/pkg1"
|
"/some/path/pkg1"
|
||||||
]
|
],
|
||||||
|
"licenses": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": {
|
"source": {
|
||||||
|
|||||||
@ -12,7 +12,8 @@
|
|||||||
"path": "/somefile-1.txt",
|
"path": "/somefile-1.txt",
|
||||||
"layerIndex": 0
|
"layerIndex": 0
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"licenses": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "package-2",
|
"name": "package-2",
|
||||||
@ -26,7 +27,8 @@
|
|||||||
"path": "/somefile-2.txt",
|
"path": "/somefile-2.txt",
|
||||||
"layerIndex": 1
|
"layerIndex": 1
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"licenses": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": {
|
"source": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user