fleet/orbit/pkg/packaging/wix/transform.go
guangwu 33858d7301
chore: remove refs to deprecated io/ioutil (#14485)
# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [ ] Documented any API changes (docs/Using-Fleet/REST-API.md or
docs/Contributing/API-for-contributors.md)
- [ ] Documented any permissions changes (docs/Using
Fleet/manage-access.md)
- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.
- [ ] Added/updated tests
- [ ] Manual QA for all new/changed functionality
  - For Orbit and Fleet Desktop changes:
- [ ] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).

Signed-off-by: guoguangwu <guoguangwu@magic-shield.com>
2023-10-27 15:28:54 -03:00

128 lines
3.2 KiB
Go

package wix
import (
"bytes"
"encoding/xml"
"fmt"
"os"
"strings"
)
type node struct {
XMLName xml.Name
Attrs attrs `xml:",any,attr"`
Content string `xml:",chardata"`
Children []*node `xml:",any"`
}
type attrs []*xml.Attr
// Get the value of the attr with the provided name, otherwise returning an
// empty string.
func (a attrs) Get(name string) string {
for _, attr := range a {
if attr.Name.Local == name {
return attr.Value
}
}
return ""
}
func xmlAttr(name, value string) *xml.Attr {
return &xml.Attr{Name: xml.Name{Local: name}, Value: value}
}
func xmlNode(name string, attrs ...*xml.Attr) *node {
return &node{
XMLName: xml.Name{Local: name},
Attrs: attrs,
}
}
func TransformHeat(path string) error {
contents, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("read file: %w", err)
}
// Eliminate line feeds (they cause extra junk in the result)
contents = bytes.ReplaceAll(contents, []byte("\r"), []byte(""))
var n node
if err := xml.Unmarshal(contents, &n); err != nil {
return fmt.Errorf("unmarshal xml: %w", err)
}
stack := []*node{}
if err := transform(&n, &stack); err != nil {
return fmt.Errorf("in transform: %w", err)
}
contents, err = xml.MarshalIndent(n, "", " ")
if err != nil {
return fmt.Errorf("marshal xml: %w", err)
}
// Remove first as we encounter permission errors on some Linux configurations.
if err := os.Remove(path); err != nil {
return fmt.Errorf("remove old file: %w", err)
}
if err := os.WriteFile(path, contents, 0o600); err != nil {
return fmt.Errorf("write file: %w", err)
}
return nil
}
func transform(cur *node, stack *[]*node) error {
// Clear namespace on all elements (generates unnecessarily noisy output if
// this is not done).
cur.XMLName.Space = ""
// Change permissions for all files
if cur.XMLName.Local == "File" {
// This SDDL copied directly from osqueryd.exe after a regular
// osquery MSI install. We assume that osquery is getting the
// permissions correct and use exactly the same for our files.
// Using this cryptic string seems to be the only way to disable
// permission inheritance in a WiX package, so we may not have
// any option for something more readable.
//
// Permissions:
// Disable inheritance
// SYSTEM: read/write/execute
// Administrators: read/write/execute
// Users: read/execute
sddl := "O:SYG:SYD:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)"
if strings.HasSuffix(cur.Attrs.Get("Source"), "secret.txt") {
// This SDDL copied from properly configured file on a Windows 10
// machine. Permissions are same as above but with access removed
// for regular users.
//
// Permissions:
// Disable inheritance
// SYSTEM: read/write/execute
// Administrators: read/write/execute
sddl = "O:SYG:SYD:PAI(A;;FA;;;SY)(A;;FA;;;BA)"
}
cur.Children = append(cur.Children, xmlNode(
"PermissionEx",
xmlAttr("Sddl", sddl),
))
}
// push current node onto stack
*stack = append(*stack, cur)
// Recursively walk the children
for _, child := range cur.Children {
if err := transform(child, stack); err != nil {
return err
}
}
// pop current node from stack
*stack = (*stack)[:len(*stack)-1]
return nil
}