Add basic xattr implementation (commiting to save it, about to delete most of it)

This commit is contained in:
David Dworken
2022-04-25 21:42:28 -07:00
parent 3e093c2e13
commit 74caf87eda
3 changed files with 135 additions and 0 deletions

View File

@ -2,6 +2,7 @@ package lib
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
@ -13,6 +14,7 @@ import (
"os/exec"
"os/user"
"path"
"regexp"
"runtime"
"strconv"
"strings"
@ -539,6 +541,14 @@ func Update() error {
}
}
// On MacOS, set the xattrs containing the signatures. These are generated by an action and pushed to a github release that we download and set
if runtime.GOOS == "darwin" {
err := setCodesigningXattrs(downloadData, "/tmp/hishtory-client")
if err != nil {
return fmt.Errorf("failed to set codesigning xattrs: %v", err)
}
}
// Install the new one
cmd := exec.Command("chmod", "+x", "/tmp/hishtory-client")
var stdout bytes.Buffer
@ -708,3 +718,72 @@ func ApiPost(path, contentType string, data []byte) ([]byte, error) {
getLogger().Printf("ApiPost(%#v): %s\n", path, duration.String())
return respBody, nil
}
func parseXattr(xattrDump string) (map[string][]byte, error) {
m := make(map[string][]byte)
nextLineIsAttrName := true
attrName := ""
attrValue := make([]byte, 0)
for _, line := range strings.Split(xattrDump, "\n") {
if nextLineIsAttrName {
attrName = line[:len(line)-1]
nextLineIsAttrName = false
} else {
r := regexp.MustCompile("\\d{8} (?P<hex>([A-Z0-9]{2} )+)\\s+\\|[^\\s]+\\|")
match := r.FindStringSubmatch(line)
if match != nil {
for i, name := range r.SubexpNames() {
if name == "hex" {
bytes, err := hex.DecodeString(strings.ReplaceAll(match[i], " ", ""))
if err != nil {
return nil, fmt.Errorf("failed to decode hex string %#v in xattr file: %v", match[i], err)
}
attrValue = append(attrValue, bytes...)
}
}
} else {
if strings.Contains(line, "|") {
return nil, fmt.Errorf("entered confusing state in xattr file on line %#v, file=%#v", line, xattrDump)
} else {
nextLineIsAttrName = true
m[attrName] = attrValue
attrValue = make([]byte, 0)
}
}
}
}
return m, nil
}
func setXattr(filename, xattrDump string) {
m, err := parseXattr(xattrDump)
if err != nil {
panic(fmt.Errorf("failed to parse xattr file: %v", err))
}
for k, v := range m {
err := syscall.Setxattr(filename, k, v, 0)
if err != nil {
panic(fmt.Errorf("failed to set xattr %#v on file %#v: %v", k, filename, err))
}
}
}
func setCodesigningXattrs(downloadInfo shared.UpdateInfo, filename string) error {
if runtime.GOOS != "darwin" {
return fmt.Errorf("setCodesigningXattrs is only supported on macOS")
}
url := ""
if runtime.GOARCH == "arm64" {
url = downloadInfo.DarwinArm64Xattr
} else if runtime.GOARCH == "amd64" {
url = downloadInfo.DarwinAmd64Xattr
} else {
return fmt.Errorf("setCodesigningXattrs only supports arm64 and amd64: %#v", runtime.GOARCH)
}
xattrDump, err := ApiGet(url)
if err != nil {
return fmt.Errorf("failed to get xattr dump: %v", err)
}
setXattr(filename, string(xattrDump))
return nil
}