Add temp keychain for backup requests

This commit is contained in:
Ali 2022-06-04 21:55:02 +04:00
parent 347155dbe7
commit 53f95864d3
10 changed files with 76 additions and 436 deletions

View File

@ -5,6 +5,6 @@
@interface MTBackupAddressSignals : NSObject
+ (MTSignal * _Nonnull)fetchBackupIps:(bool)isTestingEnvironment currentContext:(MTContext * _Nonnull)currentContext additionalSource:(MTSignal * _Nullable)additionalSource phoneNumber:(NSString * _Nullable)phoneNumber;
+ (MTSignal * _Nonnull)fetchBackupIps:(bool)isTestingEnvironment currentContext:(MTContext * _Nonnull)currentContext additionalSource:(MTSignal * _Nullable)additionalSource phoneNumber:(NSString * _Nullable)phoneNumber mainDatacenterId:(NSInteger)mainDatacenterId;
@end

View File

@ -58,6 +58,8 @@
+ (void)performWithObjCTry:(dispatch_block_t _Nonnull)block;
+ (void)copyAuthInfoFrom:(id<MTKeychain> _Nonnull)keychain toTempKeychain:(id<MTKeychain> _Nonnull)tempKeychain;
- (instancetype _Nonnull)initWithSerialization:(id<MTSerialization> _Nonnull)serialization encryptionProvider:(id<EncryptionProvider> _Nonnull)encryptionProvider apiEnvironment:(MTApiEnvironment * _Nonnull)apiEnvironment isTestingEnvironment:(bool)isTestingEnvironment useTempAuthKeys:(bool)useTempAuthKeys;
- (void)performBatchUpdates:(void (^ _Nonnull)())block;

View File

@ -1,17 +1 @@
#import <Foundation/Foundation.h>
#import <MtProtoKit/MTKeychain.h>
NS_ASSUME_NONNULL_BEGIN
@interface MTFileBasedKeychain : NSObject <MTKeychain>
+ (instancetype)unencryptedKeychainWithName:(NSString * _Nullable)name documentsPath:(NSString *)documentsPath;
+ (instancetype)keychainWithName:(NSString * _Nullable)name documentsPath:(NSString * _Nullable)documentsPath;
- (NSDictionary<NSString *, id> *)contentsForGroup:(NSString *)group;
@end
NS_ASSUME_NONNULL_END

View File

@ -8,6 +8,4 @@
- (id)objectForKey:(NSString *)aKey group:(NSString *)group;
- (void)removeObjectForKey:(NSString *)aKey group:(NSString *)group;
- (void)dropGroup:(NSString *)group;
@end

View File

@ -20,7 +20,6 @@
#import <MtProtoKit/MTDropResponseContext.h>
#import <MtProtoKit/MTEncryption.h>
#import <MtProtoKit/MTExportedAuthorizationData.h>
#import <MtProtoKit/MTFileBasedKeychain.h>
#import <MtProtoKit/MTGzip.h>
#import <MtProtoKit/MTHttpRequestOperation.h>
#import <MtProtoKit/MTIncomingMessage.h>
@ -57,4 +56,4 @@
#import <MtProtoKit/MTTimeSyncMessageService.h>
#import <MtProtoKit/MTTransport.h>
#import <MtProtoKit/MTTransportScheme.h>
#import <MtProtoKit/MTTransportTransaction.h>
#import <MtProtoKit/MTTransportTransaction.h>

View File

@ -13,6 +13,44 @@
#import <MtProtoKit/MTProto.h>
#import <MtProtoKit/MTSerialization.h>
#import <MtProtoKit/MTLogging.h>
#import <MtProtoKit/MTKeychain.h>
@interface MTTemporaryKeychain : NSObject<MTKeychain> {
NSMutableDictionary<NSString *, id> *_dict;
}
@end
@implementation MTTemporaryKeychain
- (instancetype)init {
self = [super init];
if (self != nil) {
_dict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (NSString *)itemKeyForGroup:(NSString *)group key:(NSString *)key {
return [NSString stringWithFormat:@"%@:%@", group, key];
}
- (void)setObject:(id)object forKey:(NSString *)aKey group:(NSString *)group {
if (object == nil) {
return;
}
_dict[[self itemKeyForGroup:group key:aKey]] = object;
}
- (id)objectForKey:(NSString *)aKey group:(NSString *)group {
return _dict[[self itemKeyForGroup:group key:aKey]];
}
- (void)removeObjectForKey:(NSString *)aKey group:(NSString *)group {
[_dict removeObjectForKey:[self itemKeyForGroup:group key:aKey]];
}
@end
static NSData *base64_decode(NSString *str) {
if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
@ -224,7 +262,7 @@ static NSString *makeRandomPadding() {
return [[MTSignal mergeSignals:signals] take:1];
}
+ (MTSignal *)fetchConfigFromAddress:(MTBackupDatacenterAddress *)address currentContext:(MTContext *)currentContext {
+ (MTSignal *)fetchConfigFromAddress:(MTBackupDatacenterAddress *)address currentContext:(MTContext *)currentContext mainDatacenterId:(NSInteger)mainDatacenterId {
MTApiEnvironment *apiEnvironment = [currentContext.apiEnvironment copy];
apiEnvironment = [apiEnvironment withUpdatedSocksProxySettings:nil];
@ -242,13 +280,24 @@ static NSString *makeRandomPadding() {
MTContext *context = [[MTContext alloc] initWithSerialization:currentContext.serialization encryptionProvider:currentContext.encryptionProvider apiEnvironment:apiEnvironment isTestingEnvironment:currentContext.isTestingEnvironment useTempAuthKeys:false];
NSInteger authTokenMasterDatacenterId = 0;
NSNumber *requiredAuthToken = nil;
bool allowUnboundEphemeralKeys = true;
if (address.datacenterId != 0) {
//context.keychain = currentContext.keychain;
authTokenMasterDatacenterId = mainDatacenterId;
requiredAuthToken = @(address.datacenterId);
MTTemporaryKeychain *tempKeychain = [[MTTemporaryKeychain alloc] init];
[MTContext copyAuthInfoFrom:currentContext.keychain toTempKeychain:tempKeychain];
context.keychain = tempKeychain;
allowUnboundEphemeralKeys = false;
} else {
MTTemporaryKeychain *tempKeychain = [[MTTemporaryKeychain alloc] init];
context.keychain = tempKeychain;
}
MTProto *mtProto = [[MTProto alloc] initWithContext:context datacenterId:address.datacenterId usageCalculationInfo:nil requiredAuthToken:nil authTokenMasterDatacenterId:0];
MTProto *mtProto = [[MTProto alloc] initWithContext:context datacenterId:address.datacenterId usageCalculationInfo:nil requiredAuthToken:requiredAuthToken authTokenMasterDatacenterId:authTokenMasterDatacenterId];
mtProto.useTempAuthKeys = true;
mtProto.allowUnboundEphemeralKeys = true;
mtProto.allowUnboundEphemeralKeys = allowUnboundEphemeralKeys;
MTRequestMessageService *requestService = [[MTRequestMessageService alloc] initWithContext:context];
[mtProto addMessageService:requestService];
@ -258,7 +307,6 @@ static NSString *makeRandomPadding() {
NSData *getConfigData = nil;
MTRequestDatacenterAddressListParser responseParser = [currentContext.serialization requestDatacenterAddressWithData:&getConfigData];
[request setPayload:getConfigData metadata:@"getConfig" shortMetadata:@"getConfig" responseParser:responseParser];
__weak MTContext *weakCurrentContext = currentContext;
@ -300,7 +348,7 @@ static NSString *makeRandomPadding() {
}];
}
+ (MTSignal * _Nonnull)fetchBackupIps:(bool)isTestingEnvironment currentContext:(MTContext * _Nonnull)currentContext additionalSource:(MTSignal * _Nullable)additionalSource phoneNumber:(NSString * _Nullable)phoneNumber {
+ (MTSignal * _Nonnull)fetchBackupIps:(bool)isTestingEnvironment currentContext:(MTContext * _Nonnull)currentContext additionalSource:(MTSignal * _Nullable)additionalSource phoneNumber:(NSString * _Nullable)phoneNumber mainDatacenterId:(NSInteger)mainDatacenterId {
NSMutableArray *signals = [[NSMutableArray alloc] init];
[signals addObject:[self fetchBackupIpsResolveGoogle:isTestingEnvironment phoneNumber:phoneNumber currentContext:currentContext addressOverride:currentContext.apiEnvironment.accessHostOverride]];
[signals addObject:[self fetchBackupIpsResolveCloudflare:isTestingEnvironment phoneNumber:phoneNumber currentContext:currentContext addressOverride:currentContext.apiEnvironment.accessHostOverride]];
@ -322,7 +370,7 @@ static NSString *makeRandomPadding() {
NSMutableArray *signals = [[NSMutableArray alloc] init];
NSTimeInterval delay = 0.0;
for (MTBackupDatacenterAddress *address in data.addressList) {
MTSignal *signal = [self fetchConfigFromAddress:address currentContext:currentContext];
MTSignal *signal = [self fetchConfigFromAddress:address currentContext:currentContext mainDatacenterId:mainDatacenterId];
if (delay > DBL_EPSILON) {
signal = [signal delay:delay onQueue:[[MTQueue alloc] init]];
}

View File

@ -290,6 +290,21 @@ static int32_t fixedTimeDifferenceValue = 0;
}
}
static void copyKeychainKey(NSString * _Nonnull group, NSString * _Nonnull key, id<MTKeychain> _Nonnull fromKeychain, id<MTKeychain> _Nonnull toKeychain) {
id value = [fromKeychain objectForKey:key group:group];
if (value) {
[toKeychain setObject:value forKey:key group:group];
}
}
+ (void)copyAuthInfoFrom:(id<MTKeychain> _Nonnull)keychain toTempKeychain:(id<MTKeychain> _Nonnull)tempKeychain {
copyKeychainKey(@"temp", @"globalTimeDifference", keychain, tempKeychain);
copyKeychainKey(@"persistent", @"datacenterAddressSetById", keychain, tempKeychain);
copyKeychainKey(@"persistent", @"datacenterAuthInfoById", keychain, tempKeychain);
copyKeychainKey(@"ephemeral", @"datacenterPublicKeysById", keychain, tempKeychain);
//copyKeychainKey(@"persistent", @"authTokenById", keychain, tempKeychain);
}
- (void)cleanup
{
NSDictionary *datacenterAuthActions = _datacenterAuthActions;

View File

@ -1,403 +1 @@
#import <MtProtoKit/MTFileBasedKeychain.h>
#import <MtProtoKit/MTLogging.h>
#import <pthread.h>
#define TG_SYNCHRONIZED_DEFINE(lock) pthread_mutex_t _TG_SYNCHRONIZED_##lock
#define TG_SYNCHRONIZED_INIT(lock) pthread_mutex_init(&_TG_SYNCHRONIZED_##lock, NULL)
#define TG_SYNCHRONIZED_BEGIN(lock) pthread_mutex_lock(&_TG_SYNCHRONIZED_##lock);
#define TG_SYNCHRONIZED_END(lock) pthread_mutex_unlock(&_TG_SYNCHRONIZED_##lock);
#import <CommonCrypto/CommonCrypto.h>
#import <MtProtoKit/MTEncryption.h>
static TG_SYNCHRONIZED_DEFINE(_keychains) = PTHREAD_MUTEX_INITIALIZER;
static NSMutableDictionary *keychains()
{
static NSMutableDictionary *dict = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
TG_SYNCHRONIZED_INIT(_keychains);
dict = [[NSMutableDictionary alloc] init];
});
return dict;
}
@interface MTFileBasedKeychain ()
{
NSString *_name;
bool _encrypted;
NSData *_aesKey;
NSData *_aesIv;
NSString *_documentsPath;
TG_SYNCHRONIZED_DEFINE(_dictByGroup);
NSMutableDictionary *_dictByGroup;
}
@end
@implementation MTFileBasedKeychain
+ (instancetype)unencryptedKeychainWithName:(NSString *)name documentsPath:(NSString *)documentsPath
{
if (name == nil)
return nil;
TG_SYNCHRONIZED_BEGIN(_keychains);
MTFileBasedKeychain *keychain = [keychains() objectForKey:name];
if (keychain == nil)
{
keychain = [[MTFileBasedKeychain alloc] initWithName:name documentsPath:documentsPath encrypted:false];
[keychains() setObject:keychain forKey:name];
}
TG_SYNCHRONIZED_END(_keychains);
return keychain;
}
+ (instancetype)keychainWithName:(NSString *)name documentsPath:(NSString *)documentsPath
{
if (name == nil)
return nil;
TG_SYNCHRONIZED_BEGIN(_keychains);
MTFileBasedKeychain *keychain = [keychains() objectForKey:name];
if (keychain == nil)
{
keychain = [[MTFileBasedKeychain alloc] initWithName:name documentsPath:documentsPath encrypted:true];
[keychains() setObject:keychain forKey:name];
}
TG_SYNCHRONIZED_END(_keychains);
return keychain;
}
- (instancetype)initWithName:(NSString *)name documentsPath:(NSString *)documentsPath encrypted:(bool)encrypted
{
self = [super init];
if (self != nil)
{
TG_SYNCHRONIZED_INIT(_dictByGroup);
_dictByGroup = [[NSMutableDictionary alloc] init];
_name = name;
_documentsPath = documentsPath;
_encrypted = encrypted;
if (name != nil)
{
if (_encrypted)
{
NSMutableDictionary *keychainReadQuery = [[NSMutableDictionary alloc] initWithDictionary:@{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"org.mtproto.MTKeychain",
(__bridge id)kSecAttrAccount: [[NSString alloc] initWithFormat:@"MTKeychain:%@", name],
#if TARGET_OS_IPHONE
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
#endif
(__bridge id)kSecReturnData: (id)kCFBooleanTrue,
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne
}];
bool upgradeEncryption = false;
CFDataRef keyData = NULL;
if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainReadQuery, (CFTypeRef *)&keyData) == noErr && keyData != NULL)
{
NSData *data = (__bridge_transfer NSData *)keyData;
if (data.length == 64)
{
_aesKey = [data subdataWithRange:NSMakeRange(0, 32)];
_aesIv = [data subdataWithRange:NSMakeRange(32, 32)];
}
}
else
{
keychainReadQuery[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainReadQuery, (CFTypeRef *)&keyData) == noErr && keyData != NULL)
{
NSData *data = (__bridge_transfer NSData *)keyData;
if (data.length == 64)
{
upgradeEncryption = true;
_aesKey = [data subdataWithRange:NSMakeRange(0, 32)];
_aesIv = [data subdataWithRange:NSMakeRange(32, 32)];
}
}
}
bool storeKey = upgradeEncryption || _aesKey == nil || _aesIv == nil;
if (_aesKey == nil || _aesIv == nil)
{
uint8_t buf[32];
__unused int result = 0;
result = SecRandomCopyBytes(kSecRandomDefault, 32, buf);
_aesKey = [[NSData alloc] initWithBytes:buf length:32];
result = SecRandomCopyBytes(kSecRandomDefault, 32, buf);
_aesIv = [[NSData alloc] initWithBytes:buf length:32];
}
NSMutableData *newKeyData = [[NSMutableData alloc] init];
[newKeyData appendData:_aesKey];
[newKeyData appendData:_aesIv];
if (storeKey)
{
SecItemDelete((__bridge CFDictionaryRef)@{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"org.mtproto.MTKeychain",
(__bridge id)kSecAttrAccount: [[NSString alloc] initWithFormat:@"MTKeychain:%@", name],
#if TARGET_OS_IPHONE
(__bridge id)kSecAttrAccessible: upgradeEncryption ? (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly
#endif
});
SecItemAdd((__bridge CFDictionaryRef)@{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"org.mtproto.MTKeychain",
(__bridge id)kSecAttrAccount: [[NSString alloc] initWithFormat:@"MTKeychain:%@", name],
#if TARGET_OS_IPHONE
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
#endif
(__bridge id)kSecValueData: newKeyData
}, NULL);
}
}
}
}
return self;
}
- (NSString *)filePathForName:(NSString *)name group:(NSString *)group
{
static NSString *dataDirectory = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
#if TARGET_OS_IPHONE
dataDirectory = [_documentsPath stringByAppendingPathComponent:@"mtkeychain"];
#elif TARGET_OS_MAC
NSString *applicationSupportPath = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0];
NSString *applicationName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
dataDirectory = [[applicationSupportPath stringByAppendingPathComponent:applicationName] stringByAppendingPathComponent:@"mtkeychain"];
#else
# error "Unsupported OS"
#endif
__autoreleasing NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:dataDirectory withIntermediateDirectories:true attributes:nil error:&error];
if (error != nil) {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error creating keychain directory: %@]", error);
}
}
});
return [dataDirectory stringByAppendingPathComponent:[[NSString alloc] initWithFormat:@"%@_%@.bin", name, group]];
}
- (void)_loadKeychainIfNeeded:(NSString *)group
{
if (_dictByGroup[group] == nil)
{
if (_name != nil)
{
NSData *data = [[NSData alloc] initWithContentsOfFile:[self filePathForName:_name group:group]];
if (data != nil && data.length >= 4)
{
uint32_t length = 0;
[data getBytes:&length range:NSMakeRange(0, 4)];
uint32_t paddedLength = length;
while (paddedLength % 16 != 0)
{
paddedLength++;
}
if (data.length == 4 + paddedLength || data.length == 4 + paddedLength + 4)
{
NSMutableData *encryptedData = [[NSMutableData alloc] init];
[encryptedData appendData:[data subdataWithRange:NSMakeRange(4, paddedLength)]];
NSMutableData *decryptedData = nil;
if (_encrypted) {
decryptedData = [[NSMutableData alloc] initWithData:MTAesDecrypt(encryptedData, _aesKey, _aesIv)];
} else {
decryptedData = encryptedData;
}
[decryptedData setLength:length];
bool hashVerified = true;
if (data.length == 4 + paddedLength + 4)
{
int32_t hash = 0;
[data getBytes:&hash range:NSMakeRange(4 + paddedLength, 4)];
int32_t decryptedHash = MTMurMurHash32(decryptedData.bytes, (int)decryptedData.length);
if (hash != decryptedHash)
{
if (MTLogEnabled()) {
MTLog(@"[MTKeychain invalid decrypted hash]");
}
hashVerified = false;
}
}
if (hashVerified)
{
@try
{
id object = [NSKeyedUnarchiver unarchiveObjectWithData:decryptedData];
if ([object respondsToSelector:@selector(objectForKey:)] && [object respondsToSelector:@selector(setObject:forKey:)])
_dictByGroup[group] = object;
else {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain invalid root object %@]", object);
}
}
}
@catch (NSException *e)
{
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error parsing keychain: %@]", e);
}
}
}
}
else {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error loading keychain: expected data length %d, got %d]", 4 + (int)paddedLength, (int)data.length);
}
}
}
}
if (_dictByGroup[group] == nil)
_dictByGroup[group] = [[NSMutableDictionary alloc] init];
}
}
- (void)_storeKeychain:(NSString *)group
{
if (_dictByGroup[group] != nil && _name != nil)
{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_dictByGroup[group]];
if (data != nil)
{
NSMutableData *encryptedData = [[NSMutableData alloc] initWithData:data];
int32_t hash = MTMurMurHash32(encryptedData.bytes, (int)encryptedData.length);
while (encryptedData.length % 16 != 0)
{
uint8_t random = 0;
arc4random_buf(&random, 1);
[encryptedData appendBytes:&random length:1];
}
if (_encrypted)
MTAesEncryptInplace(encryptedData, _aesKey, _aesIv);
uint32_t length = (uint32_t)data.length;
[encryptedData replaceBytesInRange:NSMakeRange(0, 0) withBytes:&length length:4];
[encryptedData appendBytes:&hash length:4];
NSString *filePath = [self filePathForName:_name group:group];
if (![encryptedData writeToFile:filePath atomically:true]) {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error writing keychain to file]");
}
}
else
{
#if TARGET_OS_IPHONE
__autoreleasing NSError *error = nil;
[[NSURL fileURLWithPath:filePath] setResourceValue:[NSNumber numberWithBool:true] forKey:NSURLIsExcludedFromBackupKey error:&error];
if (error != nil) {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error setting \"exclude from backup\" flag]");
}
}
#endif
}
}
else {
if (MTLogEnabled()) {
MTLog(@"[MTKeychain error serializing keychain]");
}
}
}
}
- (void)setObject:(id)object forKey:(id<NSCopying>)aKey group:(NSString *)group
{
if (object == nil || aKey == nil)
return;
TG_SYNCHRONIZED_BEGIN(_dictByGroup);
[self _loadKeychainIfNeeded:group];
_dictByGroup[group][aKey] = object;
[self _storeKeychain:group];
TG_SYNCHRONIZED_END(_dictByGroup);
}
- (id)objectForKey:(id<NSCopying>)aKey group:(NSString *)group
{
if (aKey == nil)
return nil;
TG_SYNCHRONIZED_BEGIN(_dictByGroup);
[self _loadKeychainIfNeeded:group];
id result = _dictByGroup[group][aKey];
TG_SYNCHRONIZED_END(_dictByGroup);
return result;
}
- (void)removeObjectForKey:(id<NSCopying>)aKey group:(NSString *)group
{
if (aKey == nil)
return;
TG_SYNCHRONIZED_BEGIN(_dictByGroup);
[self _loadKeychainIfNeeded:group];
[_dictByGroup[group] removeObjectForKey:aKey];
[self _storeKeychain:group];
TG_SYNCHRONIZED_END(_dictByGroup);
}
- (void)dropGroup:(NSString *)group
{
if (group == nil)
return;
TG_SYNCHRONIZED_BEGIN(_dictByGroup);
_dictByGroup[group] = [[NSMutableDictionary alloc] init];
[self _storeKeychain:group];
TG_SYNCHRONIZED_END(_dictByGroup);
}
- (NSDictionary<NSString *, id> *)contentsForGroup:(NSString *)group {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
TG_SYNCHRONIZED_BEGIN(_dictByGroup);
[self _loadKeychainIfNeeded:group];
[_dictByGroup[group] enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, __unused BOOL * _Nonnull stop) {
result[key] = obj;
}];
TG_SYNCHRONIZED_END(_dictByGroup);
return result;
}
@end

View File

@ -518,7 +518,7 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
#endif
if !supplementary {
context.setDiscoverBackupAddressListSignal(MTBackupAddressSignals.fetchBackupIps(testingEnvironment, currentContext: context, additionalSource: wrappedAdditionalSource, phoneNumber: phoneNumber))
context.setDiscoverBackupAddressListSignal(MTBackupAddressSignals.fetchBackupIps(testingEnvironment, currentContext: context, additionalSource: wrappedAdditionalSource, phoneNumber: phoneNumber, mainDatacenterId: datacenterId))
}
/*#if DEBUG
@ -1090,10 +1090,6 @@ class Keychain: NSObject, MTKeychain {
func removeObject(forKey aKey: String!, group: String!) {
self.remove(group + ":" + aKey)
}
func dropGroup(_ group: String!) {
}
}
#if os(iOS)
func makeCloudDataContext(encryptionProvider: EncryptionProvider) -> CloudDataContext? {

View File

@ -240,7 +240,7 @@ public class Serialization: NSObject, MTSerialization {
return Api.functions.auth.importAuthorization(id: authId, bytes: Buffer(data: bytes)).1.makeData()
}
public func requestDatacenterAddress(with data: AutoreleasingUnsafeMutablePointer<NSData?>) -> MTRequestDatacenterAddressListParser! {
public func requestDatacenterAddress(with data: AutoreleasingUnsafeMutablePointer<NSData?>) -> MTRequestDatacenterAddressListParser! {
let (_, buffer, parser) = Api.functions.help.getConfig()
data.pointee = buffer.makeData() as NSData
return { response -> MTDatacenterAddressListData? in