-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathTweak.xm
161 lines (140 loc) · 5.89 KB
/
Tweak.xm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#import "libPass.h"
#import "headers.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import <substrate.h>
#import "NSData+AES.m"
#define SETTINGS_FILE @"/var/mobile/Library/Preferences/com.bd452.libPass.plist"
// MobileGestalt stuff for UDID
extern "C" CFPropertyListRef MGCopyAnswer(CFStringRef property);
// returns the device's UDID. Because we are in SpringBoard this works
NSString* getUDID()
{
NSString *udid = (__bridge NSString*)MGCopyAnswer(CFSTR("UniqueDeviceID"));
return udid;
}
%hook SBLockStateAggregator
-(void)_updateLockState
{
%orig;
if (![self hasAnyLockState]) // device is unlocked
[[LibPass sharedInstance] deviceWasUnlockedHandler];
}
%end
%hook SBLockScreenViewController
-(void)passcodeLockViewPasscodeEntered:(SBUIPasscodeLockViewWithKeyboard*)arg1
{
//NSLog(@"LibPass: passcodeLockViewPasscodeEntered %@", [arg1 passcode]);
if ([[arg1 passcode] isKindOfClass:[NSString class]])
[[LibPass sharedInstance] passwordWasEnteredHandler:[arg1 passcode]];
else
[[LibPass sharedInstance] passwordWasEnteredHandler:[[LibPass sharedInstance] getEffectiveDevicePasscode]];
%orig;
}
%end
%hook SBDeviceLockController
- (BOOL)attemptDeviceUnlockWithPassword:(id)arg1 appRequested:(BOOL)arg2 {
BOOL result;
if ([LibPass sharedInstance].isPasscodeOn)
{
// Passcode should not be arbitrarily bypassed, but we can still run checks
result = %orig;
if (!result && [arg1 isKindOfClass:[NSString class]] && [[LibPass sharedInstance] shouldAllowPasscode:arg1])
{
// Passcode is not the system passcode but it should still be allowed access
// For example, something like TimePasscode could be possible by registering a delegate to return YES
// if the entered passcode is the correct TP passcode. LibPassword will then perform a %orig using the system
// passcode (which should be granted access), not always bypassing the passcode but allowing for
// more than passcode to be "correct"
result = %orig([[LibPass sharedInstance] getEffectiveDevicePasscode], arg2);
// We already know it isn't the correct device passcode.
// Not returning here would cause many further problems.
return result;
}
}
else
{
// Passcode should be bypassed (no matter what)
if ([[LibPass sharedInstance] isPasscodeAvailable])
result = %orig([[LibPass sharedInstance] getEffectiveDevicePasscode], arg2);
else
result = %orig; // No device passcode stored
}
if (([arg1 isEqual:@""] || arg1 == nil) && result)
return result;
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:SETTINGS_FILE];
if (!prefs)
prefs = [[NSMutableDictionary alloc] init];
if ([arg1 isKindOfClass:[NSString class]] && ![prefs[@"savedPasscode"] isKindOfClass:[NSData class]] && result)
{
[LibPass sharedInstance].devicePasscode = arg1;
[prefs setObject:[[arg1 dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:getUDID()] forKey:@"savedPasscode"];
[prefs writeToFile:SETTINGS_FILE atomically:YES];
}
else if ([prefs[@"savedPasscode"] isKindOfClass:[NSData class]])
{
NSData *passcodeData = [prefs[@"savedPasscode"] AES256DecryptWithKey:getUDID()];
[LibPass sharedInstance].devicePasscode = [NSString stringWithUTF8String:[[[NSString alloc] initWithData:passcodeData encoding:NSUTF8StringEncoding] UTF8String]];
if (result)
{
if ([LibPass sharedInstance].devicePasscode != arg1 && [arg1 isKindOfClass:[NSString class]])
{
[LibPass sharedInstance].devicePasscode = arg1;
[prefs setObject:[[arg1 dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:getUDID()] forKey:@"savedPasscode"];
[prefs writeToFile:SETTINGS_FILE atomically:YES];
}
}
}
else
{
if (![prefs[@"savedPasscode"] isKindOfClass:[NSData class]])// no passcode stored
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"LibPass"
message:@"No device passcode stored. Please unlock the device with your passcode."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
else if (result && [LibPass sharedInstance].devicePasscode != nil && [LibPass sharedInstance].devicePasscode != arg1 && [arg1 isKindOfClass:[NSString class]])
{
// Basically here are the checks:
// 1. arg1 actually is correct and a NSString
// 2. arg1 != an existing stored passcode
[LibPass sharedInstance].devicePasscode = arg1;
[prefs setObject:[[arg1 dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:getUDID()] forKey:@"savedPasscode"];
[prefs writeToFile:SETTINGS_FILE atomically:YES];
}
}
return result;
}
%end
%hook SBUserAgent
- (BOOL)deviceIsPasscodeLocked
{
// If the passcode should be bypassed return NO.
// Otherwise, return the default value
if ([LibPass sharedInstance].isPasscodeOn == NO)
return NO;
else
return %orig;
}
%end
%hook AndroidLockView
- (_Bool)isPatternRequired
{
if ([LibPass sharedInstance].toggleValue)
return NO;
return %orig;
}
%end
%ctor
{
NSDictionary *prefs = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE];
if (prefs && [prefs objectForKey:@"savedPasscode"] != nil && [prefs[@"savedPasscode"] isKindOfClass:[NSData class]])
{
NSData *passcodeData = [prefs[@"savedPasscode"] AES256DecryptWithKey:getUDID()];
[LibPass sharedInstance].devicePasscode = [NSString stringWithUTF8String:[[[NSString alloc] initWithData:passcodeData encoding:NSUTF8StringEncoding] UTF8String]];
}
}