idevice 1.1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/NOTICE +202 -0
- data/README.md +74 -0
- data/Rakefile +37 -0
- data/examples/idevimgmount +58 -0
- data/examples/idumplockdownvalues +64 -0
- data/examples/ifetchcrashreports +54 -0
- data/examples/ilistapps +38 -0
- data/examples/ilistudids +26 -0
- data/examples/ilog +35 -0
- data/examples/installipa +51 -0
- data/examples/iremoveapp +42 -0
- data/examples/irestart +26 -0
- data/examples/iscreenshotr +39 -0
- data/idevice.gemspec +33 -0
- data/lib/idevice.rb +69 -0
- data/lib/idevice/afc.rb +518 -0
- data/lib/idevice/c.rb +129 -0
- data/lib/idevice/diagnostics_relay.rb +185 -0
- data/lib/idevice/file_relay.rb +83 -0
- data/lib/idevice/heartbeat.rb +99 -0
- data/lib/idevice/house_arrest.rb +138 -0
- data/lib/idevice/idevice.rb +208 -0
- data/lib/idevice/image_mounter.rb +117 -0
- data/lib/idevice/installation_proxy.rb +193 -0
- data/lib/idevice/lockdown.rb +350 -0
- data/lib/idevice/misagent.rb +112 -0
- data/lib/idevice/mobilebackup.rb +183 -0
- data/lib/idevice/mobilebackup2.rb +174 -0
- data/lib/idevice/mobilesync.rb +306 -0
- data/lib/idevice/notification_proxy.rb +168 -0
- data/lib/idevice/plist.rb +366 -0
- data/lib/idevice/restore.rb +176 -0
- data/lib/idevice/sbservices.rb +152 -0
- data/lib/idevice/screenshotr.rb +88 -0
- data/lib/idevice/version.rb +3 -0
- data/lib/idevice/webinspector.rb +96 -0
- data/spec/afc_devicespec.rb +409 -0
- data/spec/diagnostics_relay_devicespec.rb +125 -0
- data/spec/file_relay_devicespec.rb +45 -0
- data/spec/heartbeat_devicespec.rb +39 -0
- data/spec/idevice_devicespec.rb +93 -0
- data/spec/idevice_spec.rb +29 -0
- data/spec/image_mounter_devicespec.rb +65 -0
- data/spec/installation_proxy_devicespec.rb +54 -0
- data/spec/lockdown_devicespec.rb +106 -0
- data/spec/misagent_devicespec.rb +43 -0
- data/spec/mobilebackup2_devicespec.rb +58 -0
- data/spec/mobilebackup_devicespec.rb +41 -0
- data/spec/mobilesync_devicespec.rb +62 -0
- data/spec/notification_proxy_devicespec.rb +45 -0
- data/spec/plist_spec.rb +176 -0
- data/spec/restore_devicespec.rb +72 -0
- data/spec/samples/plist.bin +0 -0
- data/spec/samples/plist.xml +10 -0
- data/spec/sbservices_devicespec.rb +64 -0
- data/spec/screenshotr_devicespec.rb +39 -0
- data/spec/spec_helper.rb +73 -0
- data/spec/webinspector_devicespec.rb +36 -0
- metadata +233 -0
data/lib/idevice/c.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require "rubygems"
|
22
|
+
require 'plist'
|
23
|
+
require "ffi"
|
24
|
+
|
25
|
+
module FFI
|
26
|
+
class MemoryPointer < Pointer
|
27
|
+
def self.from_bytes(data)
|
28
|
+
if block_given?
|
29
|
+
new(data.size) do |p|
|
30
|
+
p.write_bytes(data)
|
31
|
+
yield(p)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
p = new(data.size)
|
35
|
+
p.write_bytes(data)
|
36
|
+
p
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.null_terminated_array_of_strings(strs)
|
41
|
+
psize = FFI::MemoryPointer.size * (strs.count+1)
|
42
|
+
pstrs = strs.map{|str| FFI::MemoryPointer.from_string(str) }
|
43
|
+
if block_given?
|
44
|
+
new(psize) do |aryp|
|
45
|
+
aryp.write_array_of_pointer(pstrs)
|
46
|
+
yield(aryp)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
aryp.instance_variable_set(:@_string_pointers, pstrs) # retain reference for garbage collection
|
50
|
+
aryp.write_array_of_pointer(pstrs)
|
51
|
+
return aryp
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module Idevice
|
58
|
+
module LibHelpers
|
59
|
+
def self.included(base)
|
60
|
+
class << base
|
61
|
+
private
|
62
|
+
def _attach_helper(svcname, opts={})
|
63
|
+
idevice = opts[:idevice] || Idevice.attach(opts)
|
64
|
+
ldsvc = opts[:lockdown_service]
|
65
|
+
unless ldsvc
|
66
|
+
ldclient = opts[:lockdown_client] || LockdownClient.attach(opts.merge(idevice:idevice))
|
67
|
+
ldsvc = ldclient.start_service(svcname)
|
68
|
+
end
|
69
|
+
|
70
|
+
FFI::MemoryPointer.new(:pointer) do |p_client|
|
71
|
+
yield idevice, ldsvc, p_client
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def _unbound_list_to_array(p_unbound_list)
|
80
|
+
ret = nil
|
81
|
+
base = list = p_unbound_list.read_pointer
|
82
|
+
unless list.null?
|
83
|
+
ret = []
|
84
|
+
until list.read_pointer.null?
|
85
|
+
ret << list.read_pointer.read_string
|
86
|
+
list += FFI::TypeDefs[:pointer].size
|
87
|
+
end
|
88
|
+
C.idevice_device_list_free(base)
|
89
|
+
end
|
90
|
+
return ret
|
91
|
+
end
|
92
|
+
|
93
|
+
def _infolist_to_hash(p_infolist)
|
94
|
+
infolist = _unbound_list_to_array(p_infolist)
|
95
|
+
if infolist
|
96
|
+
return Hash[ infolist.each_slice(2).to_a.map{|k,v| [k.to_sym, v]} ]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
module C
|
103
|
+
extend FFI::Library
|
104
|
+
|
105
|
+
class ManagedOpaquePointer < FFI::AutoPointer
|
106
|
+
def initialize(pointer)
|
107
|
+
raise NoMethodError, "release() not implemented for class #{self}" unless self.class.respond_to? :release
|
108
|
+
raise ArgumentError, "Must supply a pointer to memory" unless pointer
|
109
|
+
super(pointer, self.class.method(:release))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#----------------------------------------------------------------------
|
114
|
+
ffi_lib FFI::Library::LIBC
|
115
|
+
|
116
|
+
# memory allocators
|
117
|
+
attach_function :malloc, [:size_t], :pointer
|
118
|
+
attach_function :calloc, [:size_t], :pointer
|
119
|
+
attach_function :valloc, [:size_t], :pointer
|
120
|
+
attach_function :realloc, [:pointer, :size_t], :pointer
|
121
|
+
attach_function :free, [:pointer], :void
|
122
|
+
|
123
|
+
# memory movers
|
124
|
+
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
125
|
+
attach_function :bcopy, [:pointer, :pointer, :size_t], :void
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
@@ -0,0 +1,185 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require 'idevice/c'
|
22
|
+
require 'idevice/plist'
|
23
|
+
require 'idevice/idevice'
|
24
|
+
require 'idevice/lockdown'
|
25
|
+
|
26
|
+
module Idevice
|
27
|
+
class DiagnosticsRelayError < IdeviceLibError
|
28
|
+
end
|
29
|
+
|
30
|
+
class DiagnosticsRelayClient < C::ManagedOpaquePointer
|
31
|
+
include LibHelpers
|
32
|
+
|
33
|
+
FLAG_WAIT_FOR_DISCONNECT = (1 << 1)
|
34
|
+
FLAG_DISPLAY_PASS = (1 << 2)
|
35
|
+
FLAG_DISPLAY_FAIL = (1 << 3)
|
36
|
+
|
37
|
+
REQUEST_TYPES = [
|
38
|
+
"All",
|
39
|
+
"HDMI",
|
40
|
+
"WiFi",
|
41
|
+
"GasGaugue",
|
42
|
+
"NAND",
|
43
|
+
]
|
44
|
+
|
45
|
+
def self.release(ptr)
|
46
|
+
C.diagnostics_relay_client_free(ptr) unless ptr.null?
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def self.attach(opts={})
|
51
|
+
# Note, we're not using LibHelpers#_attach_helper since we need to do the fallback to
|
52
|
+
# the old relay service name below
|
53
|
+
|
54
|
+
idevice = opts[:idevice] || Idevice.attach(opts)
|
55
|
+
ldsvc = opts[:lockdown_service]
|
56
|
+
unless ldsvc
|
57
|
+
ldclient = opts[:lockdown_client] || LockdownClient.attach(opts.merge(idevice:idevice))
|
58
|
+
ldsvc = begin
|
59
|
+
ldclient.start_service("com.apple.mobile.diagnostics_relay")
|
60
|
+
rescue LockdownError
|
61
|
+
# fall-back to old diagnostics relay service name
|
62
|
+
ldclient.start_service("com.apple.iosdiagnostics.relay")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
FFI::MemoryPointer.new(:pointer) do |p_drc|
|
67
|
+
err = C.diagnostics_relay_client_new(idevice, ldsvc, p_drc)
|
68
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
69
|
+
drc = p_drc.read_pointer
|
70
|
+
raise DiagnosticsRelayError, "diagnostics_relay_client_new returned a NULL diagnostics_relay_client_t pointer" if drc.null?
|
71
|
+
return new(drc)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def diagnostics(type="All")
|
76
|
+
FFI::MemoryPointer.new(:pointer) do |p_diags|
|
77
|
+
err = C.diagnostics_relay_request_diagnostics(self, type, p_diags)
|
78
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
79
|
+
|
80
|
+
diags = p_diags.read_pointer.read_plist_t
|
81
|
+
raise DiagnosticsRelayError, "diagnostics_relay_request_diagnostics returned null diagnostics" if diags.nil?
|
82
|
+
return diags
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def mobilegestalt(*keys)
|
87
|
+
FFI::MemoryPointer.new(:pointer) do |p_result|
|
88
|
+
err = C.diagnostics_relay_query_mobilegestalt(self, Plist_t.from_ruby(keys), p_result)
|
89
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
90
|
+
result = p_result.read_pointer.read_plist_t
|
91
|
+
raise DiagnosticsRelayError, "diagnostics_relay_query_mobilegestalt returned a null result" if result.nil?
|
92
|
+
return result
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def ioregistry_entry(name, klass)
|
97
|
+
FFI::MemoryPointer.new(:pointer) do |p_result|
|
98
|
+
err = C.diagnostics_relay_query_ioregistry_entry(self, name, klass, p_result)
|
99
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
100
|
+
result = p_result.read_pointer.read_plist_t
|
101
|
+
raise DiagnosticsRelayError, "diagnostics_relay_query_ioregistry_entry returned a null result" if result.nil?
|
102
|
+
return result
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def ioregistry_plane(plane)
|
107
|
+
FFI::MemoryPointer.new(:pointer) do |p_result|
|
108
|
+
err = C.diagnostics_relay_query_ioregistry_plane(self, plane, p_result)
|
109
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
110
|
+
result = p_result.read_pointer.read_plist_t
|
111
|
+
raise DiagnosticsRelayError, "diagnostics_relay_query_ioregistry_plane returned a null result" if result.nil?
|
112
|
+
return result
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def goodbye
|
117
|
+
err = C.diagnostics_relay_goodbye(self)
|
118
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
119
|
+
return true
|
120
|
+
end
|
121
|
+
|
122
|
+
def sleep
|
123
|
+
err = C.diagnostics_relay_sleep(self)
|
124
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
125
|
+
return true
|
126
|
+
end
|
127
|
+
|
128
|
+
def restart(flags=0)
|
129
|
+
err = C.diagnostics_relay_restart(self, flags)
|
130
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
131
|
+
return true
|
132
|
+
end
|
133
|
+
|
134
|
+
def shutdown(flags=0)
|
135
|
+
err = C.diagnostics_relay_shutdown(self, flags)
|
136
|
+
raise DiagnosticsRelayError, "Diagnostics Relay error: #{err}" if err != :SUCCESS
|
137
|
+
return true
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
module C
|
142
|
+
ffi_lib 'imobiledevice'
|
143
|
+
|
144
|
+
typedef enum(
|
145
|
+
:SUCCESS , 0,
|
146
|
+
:INVALID_ARG , -1,
|
147
|
+
:PLIST_ERROR , -2,
|
148
|
+
:MUX_ERROR , -3,
|
149
|
+
:UNKNOWN_REQUEST , -4,
|
150
|
+
:UNKNOWN_ERROR , -256,
|
151
|
+
), :diagnostics_relay_error_t
|
152
|
+
|
153
|
+
#diagnostics_relay_error_t diagnostics_relay_client_new(idevice_t device, lockdownd_service_descriptor_t service, diagnostics_relay_client_t *client);
|
154
|
+
attach_function :diagnostics_relay_client_new, [Idevice, LockdownServiceDescriptor, :pointer], :diagnostics_relay_error_t
|
155
|
+
|
156
|
+
#diagnostics_relay_error_t diagnostics_relay_client_free(diagnostics_relay_client_t client);
|
157
|
+
attach_function :diagnostics_relay_client_free, [DiagnosticsRelayClient], :diagnostics_relay_error_t
|
158
|
+
|
159
|
+
#diagnostics_relay_error_t diagnostics_relay_goodbye(diagnostics_relay_client_t client);
|
160
|
+
attach_function :diagnostics_relay_goodbye, [DiagnosticsRelayClient], :diagnostics_relay_error_t
|
161
|
+
|
162
|
+
#diagnostics_relay_error_t diagnostics_relay_sleep(diagnostics_relay_client_t client);
|
163
|
+
attach_function :diagnostics_relay_sleep, [DiagnosticsRelayClient], :diagnostics_relay_error_t
|
164
|
+
|
165
|
+
#diagnostics_relay_error_t diagnostics_relay_restart(diagnostics_relay_client_t client, int flags);
|
166
|
+
attach_function :diagnostics_relay_restart, [DiagnosticsRelayClient, :int], :diagnostics_relay_error_t
|
167
|
+
|
168
|
+
#diagnostics_relay_error_t diagnostics_relay_shutdown(diagnostics_relay_client_t client, int flags);
|
169
|
+
attach_function :diagnostics_relay_shutdown, [DiagnosticsRelayClient, :int], :diagnostics_relay_error_t
|
170
|
+
|
171
|
+
#diagnostics_relay_error_t diagnostics_relay_request_diagnostics(diagnostics_relay_client_t client, const char* type, plist_t* diagnostics);
|
172
|
+
attach_function :diagnostics_relay_request_diagnostics, [DiagnosticsRelayClient, :string, :pointer], :diagnostics_relay_error_t
|
173
|
+
|
174
|
+
#diagnostics_relay_error_t diagnostics_relay_query_mobilegestalt(diagnostics_relay_client_t client, plist_t keys, plist_t* result);
|
175
|
+
attach_function :diagnostics_relay_query_mobilegestalt, [DiagnosticsRelayClient, Plist_t, :pointer], :diagnostics_relay_error_t
|
176
|
+
|
177
|
+
#diagnostics_relay_error_t diagnostics_relay_query_ioregistry_entry(diagnostics_relay_client_t client, const char* name, const char* class, plist_t* result);
|
178
|
+
attach_function :diagnostics_relay_query_ioregistry_entry, [DiagnosticsRelayClient, :string, :string, :pointer], :diagnostics_relay_error_t
|
179
|
+
|
180
|
+
#diagnostics_relay_error_t diagnostics_relay_query_ioregistry_plane(diagnostics_relay_client_t client, const char* plane, plist_t* result);
|
181
|
+
attach_function :diagnostics_relay_query_ioregistry_plane, [DiagnosticsRelayClient, :string, :pointer], :diagnostics_relay_error_t
|
182
|
+
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require 'idevice/c'
|
22
|
+
require 'idevice/idevice'
|
23
|
+
require 'idevice/lockdown'
|
24
|
+
|
25
|
+
module Idevice
|
26
|
+
class FileRelayError < IdeviceLibError
|
27
|
+
end
|
28
|
+
|
29
|
+
class FileRelayClient < C::ManagedOpaquePointer
|
30
|
+
include LibHelpers
|
31
|
+
def self.release(ptr)
|
32
|
+
C.file_relay_client_free(ptr) unless ptr.null?
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.attach(opts={})
|
36
|
+
_attach_helper("com.apple.mobile.file_relay", opts) do |idevice,ldsvc,p_frc|
|
37
|
+
err = C.file_relay_client_new(idevice, ldsvc, p_frc)
|
38
|
+
raise FileRelayError, "File Relay error: #{err}" if err != :SUCCESS
|
39
|
+
frc = p_frc.read_pointer
|
40
|
+
raise FileRelayError, "file_relay_client_new returned a NULL client" if frc.null?
|
41
|
+
return new(frc)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def request_sources(*sources, &block)
|
46
|
+
FFI::MemoryPointer.null_terminated_array_of_strings(sources) do |p_sources|
|
47
|
+
FFI::MemoryPointer.new(:pointer) do |p_conn|
|
48
|
+
err = C.file_relay_request_sources(self, p_sources, p_conn)
|
49
|
+
raise FileRelayError, "File Relay error: #{err}" if err != :SUCCESS
|
50
|
+
conn = p_conn.read_pointer
|
51
|
+
raise FileRelayError, "file_relay_request_sources returned a NULL connection" if conn.null?
|
52
|
+
iconn = IdeviceConnection.new(conn)
|
53
|
+
ret = iconn.receive_all(nil, &block)
|
54
|
+
return ret
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module C
|
61
|
+
ffi_lib 'imobiledevice'
|
62
|
+
|
63
|
+
typedef enum(
|
64
|
+
:SUCCESS , 0,
|
65
|
+
:INVALID_ARG , -1,
|
66
|
+
:PLIST_ERROR , -2,
|
67
|
+
:MUX_ERROR , -3,
|
68
|
+
:INVALID_SOURCE , -4,
|
69
|
+
:STAGING_EMPTY , -5,
|
70
|
+
:UNKNOWN_ERROR , -256,
|
71
|
+
), :file_relay_error_t
|
72
|
+
|
73
|
+
#file_relay_error_t file_relay_client_new(idevice_t device, lockdownd_service_descriptor_t service, file_relay_client_t *client);
|
74
|
+
attach_function :file_relay_client_new, [Idevice, LockdownServiceDescriptor, :pointer], :file_relay_error_t
|
75
|
+
|
76
|
+
#file_relay_error_t file_relay_client_free(file_relay_client_t client);
|
77
|
+
attach_function :file_relay_client_free, [FileRelayClient], :file_relay_error_t
|
78
|
+
|
79
|
+
#file_relay_error_t file_relay_request_sources(file_relay_client_t client, const char **sources, idevice_connection_t *connection);
|
80
|
+
attach_function :file_relay_request_sources, [FileRelayClient, :pointer, :pointer], :file_relay_error_t
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2013 Eric Monti - Bluebox Security
|
3
|
+
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
5
|
+
# or more contributor license agreements. See the NOTICE file
|
6
|
+
# distributed with this work for additional information
|
7
|
+
# regarding copyright ownership. The ASF licenses this file
|
8
|
+
# to you under the Apache License, Version 2.0 (the
|
9
|
+
# "License"); you may not use this file except in compliance
|
10
|
+
# with the License. You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing,
|
15
|
+
# software distributed under the License is distributed on an
|
16
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
17
|
+
# KIND, either express or implied. See the License for the
|
18
|
+
# specific language governing permissions and limitations
|
19
|
+
# under the License.
|
20
|
+
|
21
|
+
require 'idevice/c'
|
22
|
+
require 'idevice/plist'
|
23
|
+
require 'idevice/idevice'
|
24
|
+
require 'idevice/lockdown'
|
25
|
+
|
26
|
+
module Idevice
|
27
|
+
class HeartbeatError < IdeviceLibError
|
28
|
+
end
|
29
|
+
|
30
|
+
class HeartbeatClient < C::ManagedOpaquePointer
|
31
|
+
include LibHelpers
|
32
|
+
|
33
|
+
def self.release(ptr)
|
34
|
+
C.heartbeat_client_free(ptr) unless ptr.null?
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.attach(opts={})
|
38
|
+
_attach_helper("com.apple.mobile.heartbeat", opts) do |idevice, ldsvc, p_hb|
|
39
|
+
err=C.heartbeat_client_new(idevice, ldsvc, p_hb)
|
40
|
+
raise HeartbeatError, "Heartbeat error: #{err}" if err != :SUCCESS
|
41
|
+
hb = p_hb.read_pointer
|
42
|
+
raise HeartbeatError, "hearbeat_client_new returned a NULL client" if hb.null?
|
43
|
+
return new(hb)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def send_plist(obj)
|
48
|
+
err = C.heartbeat_send(self, obj.to_plist_t)
|
49
|
+
raise HeartbeatError, "Heartbeat error: #{err}" if err != :SUCCESS
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
|
53
|
+
def receive_plist(timeout=nil)
|
54
|
+
timeout ||= 1
|
55
|
+
|
56
|
+
FFI::MemoryPointer.new(:pointer) do |p_plist|
|
57
|
+
err = C.heartbeat_receive_with_timeout(self, p_plist, timeout)
|
58
|
+
raise HeartbeatError, "Heartbeat error: #{err}" if err != :SUCCESS
|
59
|
+
plist = p_plist.read_pointer
|
60
|
+
raise HeartbeatError, "hearbeat_receive returned a NULL plist" if plist.null?
|
61
|
+
return Plist.new(plist).to_ruby
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
module C
|
68
|
+
ffi_lib 'imobiledevice'
|
69
|
+
|
70
|
+
typedef enum(
|
71
|
+
:SUCCESS , 0,
|
72
|
+
:INVALID_ARG , -1,
|
73
|
+
:PLIST_ERROR , -2,
|
74
|
+
:MUX_ERROR , -3,
|
75
|
+
:SSL_ERROR , -4,
|
76
|
+
:UNKNOWN_ERROR, -256,
|
77
|
+
), :heartbeat_error_t
|
78
|
+
|
79
|
+
|
80
|
+
#heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t service, heartbeat_client_t * client);
|
81
|
+
attach_function :heartbeat_client_new, [Idevice, LockdownServiceDescriptor, :pointer], :heartbeat_error_t
|
82
|
+
|
83
|
+
#heartbeat_error_t heartbeat_client_start_service(idevice_t device, heartbeat_client_t * client, const char* label);
|
84
|
+
attach_function :heartbeat_client_start_service, [Idevice, :pointer, :string], :heartbeat_error_t
|
85
|
+
|
86
|
+
#heartbeat_error_t heartbeat_client_free(heartbeat_client_t client);
|
87
|
+
attach_function :heartbeat_client_free, [HeartbeatClient], :heartbeat_error_t
|
88
|
+
|
89
|
+
#heartbeat_error_t heartbeat_send(heartbeat_client_t client, plist_t plist);
|
90
|
+
attach_function :heartbeat_send, [HeartbeatClient, Plist_t], :heartbeat_error_t
|
91
|
+
|
92
|
+
#heartbeat_error_t heartbeat_receive(heartbeat_client_t client, plist_t * plist);
|
93
|
+
attach_function :heartbeat_receive, [HeartbeatClient, :pointer], :heartbeat_error_t
|
94
|
+
|
95
|
+
#heartbeat_error_t heartbeat_receive_with_timeout(heartbeat_client_t client, plist_t * plist, uint32_t timeout_ms);
|
96
|
+
attach_function :heartbeat_receive_with_timeout, [HeartbeatClient, :pointer, :uint32], :heartbeat_error_t
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|