Skip to content

Commit

Permalink
feat: add afc.WalkDirectory
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanhitt committed Aug 12, 2024
1 parent c06bea3 commit 46947e3
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 25 deletions.
103 changes: 103 additions & 0 deletions afc/afc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package afc

// #cgo pkg-config: libimobiledevice-1.0
// #include <stdlib.h>
// #include <libimobiledevice/afc.h>
// int afc_length(char **arr)
// {
// int length = 0;
// int k = 0;
// for (k = 0; arr[k] != NULL; k++) {
// length = length + 1;
// }
// return length;
// }
import "C"
import (
"unsafe"

"github.com/nowsecure/goidevice/idevice"
"github.com/nowsecure/goidevice/lockdown"
)

type AFC struct {
a C.afc_client_t
}

func NewClient(device idevice.Device, svc *lockdown.Service) (*AFC, error) {
var a C.afc_client_t
err := resultToError(
C.afc_client_new(
(C.idevice_t)(idevice.GetPointer(device)),
(C.lockdownd_service_descriptor_t)(svc.GetDescriptor()),
&a,
),
)
return &AFC{a}, err
}

func (a *AFC) WalkDirectory(path string) ([]SourceFile, error) {
dir, err := a.ReadDirectory(path)
if err != nil {
return []SourceFile{}, err
}

files := []SourceFile{}
for _, f := range dir {
if f.format == "S_IFDIR" {
childDir, err := a.WalkDirectory(f.Name)
if err != nil {
return []SourceFile{}, err
}
files = append(files, childDir...)
continue
}
files = append(files, f)
}
return files, nil
}

type SourceFile struct {
Name string

format string
}

func (a *AFC) ReadDirectory(path string) ([]SourceFile, error) {
var directoryC **C.char
defer C.afc_dictionary_free(directoryC)

sourceFiles := []SourceFile{}
pathC := C.CString(path)
defer C.free(unsafe.Pointer(pathC))

err := resultToError(C.afc_read_directory(a.a, pathC, &directoryC))
if err != nil {
return []SourceFile{}, err
}

directory := unsafe.Slice(directoryC, C.afc_length(directoryC))
for i := range directory {
file := SourceFile{
Name: C.GoString(directory[i]),
}
if file.Name == ".." || file.Name == "." {
continue
}

var fileInfoC **C.char
C.afc_get_file_info(a.a, directory[i], &fileInfoC)
if fileInfoC != nil {
fileInfo := unsafe.Slice(fileInfoC, C.afc_length(fileInfoC))

for j := 0; j < len(fileInfo); j += 2 {
if C.GoString(fileInfo[j]) == "st_ifmt" {
file.format = C.GoString(fileInfo[j+1])
}
}
}
C.afc_dictionary_free(fileInfoC)
sourceFiles = append(sourceFiles, file)
}
return sourceFiles, nil
}
20 changes: 20 additions & 0 deletions afc/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package afc

// #cgo pkg-config: libimobiledevice-1.0
// #include <stdlib.h>
// #include <libimobiledevice/afc.h>
import "C"
import (
"errors"
"fmt"
)

func resultToError(result C.afc_error_t) error {
switch result {
case 0:
return nil
default:
fmt.Println(result)
return errors.New("unknown")
}
}
2 changes: 1 addition & 1 deletion installation/installation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package installation
//
// void instproxy_client_options_add_pair(plist_t client_opts, char * key, char * value)
// {
// instproxy_client_options_add(client_opts, key, value, NULL);
// instproxy_client_options_add(client_opts, key, value, NULL);
// }
import "C"
import (
Expand Down
22 changes: 22 additions & 0 deletions lockdown/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package lockdown

// #cgo pkg-config: libimobiledevice-1.0
// #include <libimobiledevice/lockdown.h>
// #include <libimobiledevice/service.h>
import "C"
import (
"errors"
Expand Down Expand Up @@ -174,3 +175,24 @@ func resultToError(result C.lockdownd_error_t) error {
return ErrUnknown
}
}

func serviceResultToError(result C.service_error_t) error {
switch result {
case 0:
return nil
case -1:
return errors.New("invalid args")
case -3:
return errors.New("mux error")
case -4:
return errors.New("ssl error")
case -5:
return errors.New("start service error")
case -6:
return errors.New("not enough data error")
case -7:
return errors.New("timeout")
default:
return errors.New("unknown")
}
}
64 changes: 45 additions & 19 deletions lockdown/lockdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ type Client interface {
ValidatePair() error
DeviceName() (string, error)
PList(domain string) (*plist.PList, error)
Close() error
Free() error
GetClient() unsafe.Pointer
StartService(d idevice.Device, serviceName string) (*Service, error)
StartServiceClient(d idevice.Device, serviceName string) (*Service, error)
}

type client struct {
Expand Down Expand Up @@ -99,39 +101,63 @@ func (s *client) PList(domain string) (*plist.PList, error) {
return list, nil
}

func (s *client) Close() error {
err := resultToError(C.lockdownd_client_free(s.p))
if err == nil {
s.p = nil
}
return err
func (s *client) Free() error {
return resultToError(C.lockdownd_client_free(s.p))
}

type Service struct {
s C.service_client_t
func (s *client) GetClient() unsafe.Pointer {
return unsafe.Pointer(s.p)
}

const (
CRASH_REPORT_MOVER_SERVICE = "com.apple.crashreportmover"
)
// GetDescriptor gets the lockdown descriptor for the service
func (s *Service) GetDescriptor() unsafe.Pointer {
return unsafe.Pointer(s.descriptor)
}

func (s *Service) FreeDescriptor() {
C.lockdownd_service_descriptor_free(s.descriptor)
}

func (s *Service) Free() {
C.lockdownd_service_descriptor_free(s.descriptor)
C.service_client_free(s.s)
}

func (s *client) StartService(d idevice.Device, serviceName string) (*Service, error) {
var p C.lockdownd_service_descriptor_t

svc := C.CString(serviceName)
defer C.free(unsafe.Pointer(svc))
err := resultToError(C.lockdownd_start_service(s.p, svc, &p))
if err != nil {
return nil, err
}

var c C.service_client_t
res := C.service_client_new((C.idevice_t)(idevice.GetPointer(d)), p, &c)
C.lockdownd_service_descriptor_free(p)
if res != 0 {
return nil, errors.New(":(")
return &Service{descriptor: p}, nil
}

type Service struct {
s C.service_client_t
descriptor C.lockdownd_service_descriptor_t
}

const (
CRASH_REPORT_MOVER_SERVICE = "com.apple.crashreportmover"
CRASH_REPORT_COPY_MOBILE_SERVICE = "com.apple.crashreportcopymobile"
)

func (s *client) StartServiceClient(d idevice.Device, serviceName string) (*Service, error) {
svc, err := s.StartService(d, serviceName)
if err != nil {
return nil, err
}
return &Service{c}, nil

err = serviceResultToError(
C.service_client_new((C.idevice_t)(idevice.GetPointer(d)),
svc.descriptor,
&svc.s,
),
)
return svc, err
}

func (s *Service) ReadPing() error {
Expand Down
27 changes: 22 additions & 5 deletions thing/main.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
package main

import (
"fmt"
"log"
"os"

"github.com/nowsecure/goidevice/afc"
"github.com/nowsecure/goidevice/idevice"
"github.com/nowsecure/goidevice/lockdown"
)

func main() {
device, err := idevice.New(os.Args[1])
device, err := idevice.New("bd133240a37062e545bbbbf664f0011c9f45895d")
if err != nil {
log.Fatal(err)
}
lock, err := lockdown.NewClientWithHandshake(device, "thingy")
if err != nil {
log.Fatal(err)
}
client, err := lock.StartService(device, lockdown.CRASH_REPORT_MOVER_SERVICE)
client, err := lock.StartServiceClient(device, lockdown.CRASH_REPORT_MOVER_SERVICE)
if err != nil {
log.Fatal(err)
}
defer client.Free()
err = client.ReadPing()
if err != nil {
log.Fatal(err)
} else {
log.Println("yay we did it")
}

service, err := lock.StartService(device, lockdown.CRASH_REPORT_COPY_MOBILE_SERVICE)
if err != nil {
log.Fatal(err)
}
defer service.Free()

afc, err := afc.NewClient(device, service)
if err != nil {
log.Fatal(err)
}
k, _ := afc.WalkDirectory(".")
for _, v := range k {
fmt.Println(v)
}

log.Println("yay we did it")
}
7 changes: 7 additions & 0 deletions thing/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "testing"

func Test_ke(t *testing.T) {
main()
}

0 comments on commit 46947e3

Please sign in to comment.