Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions acquisition/acquisition.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
rt "github.com/botherder/go-savetime/runtime"
"github.com/google/uuid"
"github.com/mvt-project/androidqf/adb"
"github.com/mvt-project/androidqf/assets"
"github.com/mvt-project/androidqf/log"
"github.com/mvt-project/androidqf/utils"
)
Expand All @@ -30,6 +29,7 @@ type Acquisition struct {
UUID string `json:"uuid"`
AndroidQFVersion string `json:"androidqf_version"`
StoragePath string `json:"storage_path"`
BaseDir string `json:"base_dir"`
Started time.Time `json:"started"`
Completed time.Time `json:"completed"`
Collector *adb.Collector `json:"collector"`
Expand All @@ -56,6 +56,7 @@ func New(path string) (*Acquisition, error) {
} else {
acq.StoragePath = path
}
acq.BaseDir = filepath.Dir(acq.StoragePath)
// Check if the path exist
stat, err := os.Stat(acq.StoragePath)
if os.IsNotExist(err) {
Expand Down Expand Up @@ -83,7 +84,7 @@ func New(path string) (*Acquisition, error) {
acq.Collector = coll

// Try to initialize encrypted streaming mode
encWriter, err := NewEncryptedZipWriter(acq.UUID)
encWriter, err := NewEncryptedZipWriter(acq.UUID, acq.BaseDir)
if err != nil {
// No key file or encryption setup failed, use normal mode
log.Debug("Encrypted streaming not available, using normal mode")
Expand Down Expand Up @@ -175,9 +176,9 @@ func (a *Acquisition) Complete() {
a.Collector.Clean()
}

// Stop ADB server before trying to remove extracted assets
// Stop ADB server, then clean up any temp directory used for bundled assets.
adb.Client.KillServer()
assets.CleanAssets()
adb.Client.Cleanup()
}

func (a *Acquisition) GetSystemInformation() error {
Expand Down
8 changes: 3 additions & 5 deletions acquisition/encrypted_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"time"

"filippo.io/age"
saveRuntime "github.com/botherder/go-savetime/runtime"
"github.com/mvt-project/androidqf/log"
)

Expand All @@ -30,9 +29,8 @@ type EncryptedZipWriter struct {
}

// NewEncryptedZipWriter creates a new encrypted zip writer if key.txt exists
func NewEncryptedZipWriter(uuid string) (*EncryptedZipWriter, error) {
cwd := saveRuntime.GetExecutableDirectory()
keyFilePath := filepath.Join(cwd, "key.txt")
func NewEncryptedZipWriter(uuid, baseDir string) (*EncryptedZipWriter, error) {
keyFilePath := filepath.Join(baseDir, "key.txt")

// Check if key file exists
if _, err := os.Stat(keyFilePath); os.IsNotExist(err) {
Expand All @@ -55,7 +53,7 @@ func NewEncryptedZipWriter(uuid string) (*EncryptedZipWriter, error) {

// Create output file
encFileName := fmt.Sprintf("%s.zip.age", uuid)
outputPath := filepath.Join(cwd, encFileName)
outputPath := filepath.Join(baseDir, encFileName)

file, err := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
Expand Down
9 changes: 3 additions & 6 deletions acquisition/secure.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"strings"

"filippo.io/age"
saveRuntime "github.com/botherder/go-savetime/runtime"
"github.com/mvt-project/androidqf/log"
)

Expand Down Expand Up @@ -44,17 +43,15 @@ func (a *Acquisition) StoreSecurely() error {
return nil
}

cwd := saveRuntime.GetExecutableDirectory()

keyFilePath := filepath.Join(cwd, "key.txt")
keyFilePath := filepath.Join(a.BaseDir, "key.txt")
if _, err := os.Stat(keyFilePath); os.IsNotExist(err) {
return nil
}

log.Info("You provided an age public key, storing the acquisition securely.")

zipFileName := fmt.Sprintf("%s.zip", a.UUID)
zipFilePath := filepath.Join(cwd, zipFileName)
zipFilePath := filepath.Join(a.BaseDir, zipFileName)

log.Info("Compressing the acquisition folder. This might take a while...")

Expand Down Expand Up @@ -83,7 +80,7 @@ func (a *Acquisition) StoreSecurely() error {
defer zipFile.Close()

encFileName := fmt.Sprintf("%s.age", zipFileName)
encFilePath := filepath.Join(cwd, encFileName)
encFilePath := filepath.Join(a.BaseDir, encFileName)
encFile, err := os.OpenFile(encFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600)
if err != nil {
return fmt.Errorf("unable to create encrypted file: %v", err)
Expand Down
15 changes: 13 additions & 2 deletions adb/adb.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package adb
import (
"errors"
"fmt"
"os"
"os/exec"
"strings"

Expand All @@ -16,8 +17,18 @@ import (
)

type ADB struct {
ExePath string
Serial string
ExePath string
Serial string
TmpAssetsDir string
}

// Cleanup removes the temporary directory used to store extracted adb assets,
// if one was created. It is a no-op when the system adb was used instead.
func (a *ADB) Cleanup() {
if a.TmpAssetsDir != "" {
os.RemoveAll(a.TmpAssetsDir)
a.TmpAssetsDir = ""
}
}

var Client *ADB
Expand Down
28 changes: 19 additions & 9 deletions adb/adb_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,35 @@
package adb

import (
"fmt"
"os"
"os/exec"
"path/filepath"

saveRuntime "github.com/botherder/go-savetime/runtime"
"github.com/mvt-project/androidqf/assets"
)

func (a *ADB) findExe() error {
err := assets.DeployAssets()
// Prefer a system-installed adb (covers distro packages where adb is on PATH).
if path, err := exec.LookPath("adb"); err == nil {
a.ExePath = path
return nil
}

// Fall back to the bundled binary. Extract it into a temp directory so we
// never try to write next to the executable (which may be /usr/bin or
// another read-only system path).
tmpDir, err := os.MkdirTemp("", "androidqf-adb-*")
if err != nil {
return err
return fmt.Errorf("failed to create temp dir for adb: %v", err)
}

adbPath, err := exec.LookPath("adb")
if err == nil {
a.ExePath = adbPath
return nil
} else {
a.ExePath = filepath.Join(saveRuntime.GetExecutableDirectory(), "adb")
if err := assets.DeployAssetsToDir(tmpDir); err != nil {
os.RemoveAll(tmpDir)
return fmt.Errorf("failed to deploy bundled adb: %v", err)
}

a.ExePath = filepath.Join(tmpDir, "adb")
a.TmpAssetsDir = tmpDir
return nil
}
27 changes: 19 additions & 8 deletions adb/adb_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,35 @@
package adb

import (
"fmt"
"os"
"os/exec"
"path/filepath"

saveRuntime "github.com/botherder/go-savetime/runtime"
"github.com/mvt-project/androidqf/assets"
)

func (a *ADB) findExe() error {
err := assets.DeployAssets()
// Prefer a system-installed adb (covers distro packages where adb is on PATH).
if path, err := exec.LookPath("adb"); err == nil {
a.ExePath = path
return nil
}

// Fall back to the bundled binary. Extract it into a temp directory so we
// never try to write next to the executable (which may be /usr/bin or
// another read-only system path).
tmpDir, err := os.MkdirTemp("", "androidqf-adb-*")
if err != nil {
return err
return fmt.Errorf("failed to create temp dir for adb: %v", err)
}

adbPath, err := exec.LookPath("adb")
if err == nil {
a.ExePath = adbPath
} else {
a.ExePath = filepath.Join(saveRuntime.GetExecutableDirectory(), "adb")
if err := assets.DeployAssetsToDir(tmpDir); err != nil {
os.RemoveAll(tmpDir)
return fmt.Errorf("failed to deploy bundled adb: %v", err)
}

a.ExePath = filepath.Join(tmpDir, "adb")
a.TmpAssetsDir = tmpDir
return nil
}
45 changes: 26 additions & 19 deletions adb/adb_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package adb

import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
Expand All @@ -16,28 +17,34 @@ import (
)

func (a *ADB) findExe() error {
// TODO: only deploy assets when needed
err := assets.DeployAssets()
// Prefer a system-installed adb (covers distro packages where adb is on PATH).
if path, err := exec.LookPath("adb.exe"); err == nil {
a.ExePath = path
return nil
}

// Fall back to the bundled binary. Extract it (and the required DLLs) into
// a temp directory so we never try to write next to the executable (which
// may be a read-only system path).
tmpDir, err := os.MkdirTemp("", "androidqf-adb-*")
if err != nil {
return err
return fmt.Errorf("failed to create temp dir for adb: %v", err)
}

adbPath, err := exec.LookPath("adb.exe")
if err == nil {
a.ExePath = adbPath
} else {
// Get path of the current directory
ex, err := os.Executable()
if err != nil {
return err
}
// Need full path to bypass go 1.19 restrictions about local path
a.ExePath = filepath.Join(filepath.Dir(ex), "adb.exe")
_, err = os.Stat(a.ExePath)
if err != nil {
log.Debugf("ADB doesn't exist at %s", a.ExePath)
return errors.New("Impossible to find ADB")
}
if err := assets.DeployAssetsToDir(tmpDir); err != nil {
os.RemoveAll(tmpDir)
return fmt.Errorf("failed to deploy bundled adb: %v", err)
}

// Need full path to bypass Go 1.19+ restrictions about relative executable paths.
exePath := filepath.Join(tmpDir, "adb.exe")
if _, err := os.Stat(exePath); err != nil {
os.RemoveAll(tmpDir)
log.Debugf("ADB doesn't exist at %s", exePath)
return errors.New("impossible to find ADB")
}

a.ExePath = exePath
a.TmpAssetsDir = tmpDir
return nil
}
30 changes: 24 additions & 6 deletions adb/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"strings"

"github.com/mvt-project/androidqf/log"

"github.com/mvt-project/androidqf/assets"
)

Expand Down Expand Up @@ -112,13 +111,32 @@ func (c *Collector) Install() error {
}

log.Debugf("Deploying collector binary '%s' for architecture '%s'.", collectorName, c.Architecture)
collectorBinary, err := assets.Collector.ReadFile(collectorName)
if err != nil {
// Somehow the file doesn't exist
return errors.New("couldn't find the collector binary")

// If the caller has pointed us at a directory of pre-built collector
// binaries (e.g. a distro package placing them under
// /usr/lib/androidqf/android-collector/), use those in preference to the
// embedded assets. This lets packagers ship the collectors separately
// without patching the source, while portable-binary users get the
// embedded fallback automatically.
var collectorBinary []byte
if collectorDir := os.Getenv("ANDROIDQF_COLLECTOR_DIR"); collectorDir != "" {
data, readErr := os.ReadFile(filepath.Join(collectorDir, collectorName))
if readErr == nil {
collectorBinary = data
log.Debugf("Using collector from ANDROIDQF_COLLECTOR_DIR: %s", collectorDir)
} else {
log.Debugf("ANDROIDQF_COLLECTOR_DIR set but could not read collector: %v — falling back to embedded", readErr)
}
}
if len(collectorBinary) == 0 {
var err error
collectorBinary, err = assets.Collector.ReadFile(collectorName)
if err != nil {
return errors.New("couldn't find the collector binary")
}
}

collectorTemp, _ := os.CreateTemp("", "collector_")
collectorTemp, err := os.CreateTemp("", "collector_")
if err != nil {
return err
}
Expand Down
Loading
Loading