Fixed parsing Opera PE self-extracting archive. (#23751)

#23540 

Tested installers from Google drive:
https://drive.google.com/drive/folders/1MZVwgZu5Af7JnSnKCFknRPGDXM29mOa6

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality

---------

Co-authored-by: Sarah Gillespie <73313222+gillespi314@users.noreply.github.com>
This commit is contained in:
Victor Lyuboslavsky 2024-11-18 16:09:29 -06:00 committed by GitHub
parent 698e9e80fe
commit 687ce3a71a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 44 additions and 10 deletions

1
changes/23540-pe-sfx Normal file
View file

@ -0,0 +1 @@
Fixed name/version parsing issue with PE (EXE) installer self-extracting archives such as Opera.

3
go.mod
View file

@ -93,7 +93,7 @@ require (
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/rs/zerolog v1.32.0
github.com/russellhaering/goxmldsig v1.2.0
github.com/saferwall/pe v1.5.2
github.com/saferwall/pe v1.5.5
github.com/sassoftware/relic/v8 v8.0.1
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9
github.com/sethvargo/go-password v0.3.0
@ -293,6 +293,7 @@ require (
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect
github.com/secure-systems-lab/go-securesystemslib v0.5.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect

6
go.sum
View file

@ -1026,14 +1026,16 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/saferwall/pe v1.5.2 h1:h5lLtLsyxGHQ9dN6cd8EfeLEBEo5gdqJpkuw4o4vTMY=
github.com/saferwall/pe v1.5.2/go.mod h1:SNzv3cdgk8SBI0UwHfyTcdjawfdnN+nbydnEL7GZ25s=
github.com/saferwall/pe v1.5.5 h1:GGbzKjXDm7i+1K6riOgtgblyTdRmTbr3r11IzjovAK8=
github.com/saferwall/pe v1.5.5/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ=
github.com/sassoftware/relic/v8 v8.0.1 h1:uYUoaoTQMs67up8/46NgrSxSftgfY4VWBusDVg56k7I=
github.com/sassoftware/relic/v8 v8.0.1/go.mod h1:s/MwugRcovgYcNJNOyvLfqRHDX7iArHtFtUR9kEodz8=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d h1:RQqyEogx5J6wPdoxqL132b100j8KjcVHO1c0KLRoIhc=
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d/go.mod h1:PegD7EVqlN88z7TpCqH92hHP+GBpfomGCCnw1PFtNOA=
github.com/secure-systems-lab/go-securesystemslib v0.5.0 h1:oTiNu0QnulMQgN/hLK124wJD/r2f9ZhIUuKIeBsCBT8=
github.com/secure-systems-lab/go-securesystemslib v0.5.0/go.mod h1:uoCqUC0Ap7jrBSEanxT+SdACYJTVplRXWLkGMuDjXqk=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=

View file

@ -48,21 +48,51 @@ func ExtractPEMetadata(tfr *fleet.TempFileReader) (*InstallerMetadata, error) {
return nil, fmt.Errorf("error parsing PE file: %w", err)
}
v, err := pep.ParseVersionResources()
resources, err := pep.ParseVersionResourcesForEntries()
if err != nil {
return nil, fmt.Errorf("error parsing PE version resources: %w", err)
}
name := strings.TrimSpace(v["ProductName"])
var name, version, sfxName, sfxVersion string
for _, e := range resources {
productName, ok := e["ProductName"]
if !ok {
productName = e["productname"] // used by Opera SFX (self-extracting archive)
}
productVersion := strings.TrimSpace(e["ProductVersion"])
if productName != "" {
productName = strings.TrimSpace(productName)
if productName == "7-Zip" {
// This may be a 7-Zip self-extracting archive.
sfxName = productName
sfxVersion = productVersion
continue
}
name = productName
}
if productVersion != "" {
version = productVersion
}
}
if name == "" && sfxName != "" {
// If we didn't find a ProductName, we may be
// dealing with an archive executable (e.g., if we're dealing with the 7-Zip executable itself rather than Opera)
name = sfxName
if sfxVersion != "" {
version = sfxVersion
}
}
return applySpecialCases(&InstallerMetadata{
Name: name,
Version: strings.TrimSpace(v["ProductVersion"]),
Version: version,
PackageIDs: []string{name},
SHASum: h.Sum(nil),
}, v), nil
}, resources), nil
}
var exeSpecialCases = map[string]func(*InstallerMetadata, map[string]string) *InstallerMetadata{
"Notion": func(meta *InstallerMetadata, resources map[string]string) *InstallerMetadata {
var exeSpecialCases = map[string]func(*InstallerMetadata, []map[string]string) *InstallerMetadata{
"Notion": func(meta *InstallerMetadata, _ []map[string]string) *InstallerMetadata {
if meta.Version != "" {
meta.Name = meta.Name + " " + meta.Version
}
@ -82,7 +112,7 @@ var exeSpecialCases = map[string]func(*InstallerMetadata, map[string]string) *In
// least for the most popular apps that use unusual naming.
//
// See https://github.com/fleetdm/fleet/issues/20440#issuecomment-2260500661
func applySpecialCases(meta *InstallerMetadata, resources map[string]string) *InstallerMetadata {
func applySpecialCases(meta *InstallerMetadata, resources []map[string]string) *InstallerMetadata {
if fn := exeSpecialCases[meta.Name]; fn != nil {
return fn(meta, resources)
}