Merge branches 'master' and 'master' of https://github.com/peter-iakovlev/MtProtoKit

This commit is contained in:
Mikhail Filimonov
2018-04-27 18:00:35 +04:00
6 changed files with 185 additions and 116 deletions

View File

@@ -2,6 +2,7 @@
#if defined(MtProtoKitDynamicFramework)
# import <MTProtoKitDynamic/MTSignal.h>
# import <MTProtoKitDynamic/MTQueue.h>
# import <MTProtoKitDynamic/MTHttpRequestOperation.h>
# import <MTProtoKitDynamic/MTEncryption.h>
# import <MTProtoKitDynamic/MTRequestMessageService.h>
@@ -15,6 +16,7 @@
# import <MTProtoKitDynamic/MTLogging.h>
#elif defined(MtProtoKitMacFramework)
# import <MTProtoKitMac/MTSignal.h>
# import <MTProtoKitMac/MTQueue.h>
# import <MTProtoKitMac/MTHttpRequestOperation.h>
# import <MTProtoKitMac/MTEncryption.h>
# import <MTProtoKitMac/MTRequestMessageService.h>
@@ -28,6 +30,7 @@
# import <MTProtoKitMac/MTLogging.h>
#else
# import <MTProtoKit/MTSignal.h>
# import <MTProtoKit/MTQueue.h>
# import <MTProtoKit/MTHttpRequestOperation.h>
# import <MTProtoKit/MTEncryption.h>
# import <MTProtoKit/MTRequestMessageService.h>
@@ -46,7 +49,7 @@
+ (MTSignal *)fetchBackupIpsGoogle:(bool)isTesting {
NSDictionary *headers = @{@"Host": @"dns-telegram.appspot.com"};
return [[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:isTesting ? @"https://google.com/test/" : @"https://google.com/"] headers:headers] mapToSignal:^MTSignal *(NSData *data) {
return [[[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:isTesting ? @"https://google.com/test/" : @"https://google.com/"] headers:headers] mapToSignal:^MTSignal *(NSData *data) {
NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];
NSData *result = [[NSData alloc] initWithBase64EncodedString:text options:NSDataBase64DecodingIgnoreUnknownCharacters];
@@ -58,13 +61,15 @@
} else {
return [MTSignal complete];
};
}] catch:^MTSignal *(__unused id error) {
return [MTSignal complete];
}];
}
+ (MTSignal *)fetchBackupIpsAzure:(bool)isTesting {
NSDictionary *headers = @{@"Host": @"tcdnb.azureedge.net"};
return [[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:isTesting ? @"https://software-download.microsoft.com/test/config.txt" : @"https://software-download.microsoft.com/prod/config.txt"] headers:headers] mapToSignal:^MTSignal *(NSData *data) {
return [[[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:isTesting ? @"https://software-download.microsoft.com/test/config.txt" : @"https://software-download.microsoft.com/prod/config.txt"] headers:headers] mapToSignal:^MTSignal *(NSData *data) {
NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];
NSData *result = [[NSData alloc] initWithBase64EncodedString:text options:NSDataBase64DecodingIgnoreUnknownCharacters];
@@ -76,13 +81,15 @@
} else {
return [MTSignal complete];
};
}] catch:^MTSignal *(__unused id error) {
return [MTSignal complete];
}];
}
+ (MTSignal *)fetchBackupIpsResolveGoogle:(bool)isTesting {
NSDictionary *headers = @{@"Host": @"dns.google.com"};
return [[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:[NSString stringWithFormat:@"https://google.com/resolve?name=%@&type=16", isTesting ? @"tap.stel.com" : @"ap.stel.com"]] headers:headers] mapToSignal:^MTSignal *(NSData *data) {
return [[[MTHttpRequestOperation dataForHttpUrl:[NSURL URLWithString:[NSString stringWithFormat:@"https://google.com/resolve?name=%@&type=16", isTesting ? @"tap.stel.com" : @"ap.stel.com"]] headers:headers] mapToSignal:^MTSignal *(NSData *data) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([dict respondsToSelector:@selector(objectForKey:)]) {
NSArray *answer = dict[@"Answer"];
@@ -119,6 +126,83 @@
}
}
return [MTSignal complete];
}] catch:^MTSignal *(__unused id error) {
return [MTSignal complete];
}];
}
+ (MTSignal *)fetchConfigFromAddress:(MTBackupDatacenterAddress *)address datacenterId:(NSInteger)datacenterId currentContext:(MTContext *)currentContext {
MTApiEnvironment *apiEnvironment = [currentContext.apiEnvironment copy];
NSMutableDictionary *datacenterAddressOverrides = [[NSMutableDictionary alloc] init];
datacenterAddressOverrides[@(datacenterId)] = [[MTDatacenterAddress alloc] initWithIp:address.ip port:(uint16_t)address.port preferForMedia:false restrictToTcp:false cdn:false preferForProxy:false secret:nil];
apiEnvironment.datacenterAddressOverrides = datacenterAddressOverrides;
apiEnvironment.apiId = currentContext.apiEnvironment.apiId;
apiEnvironment.layer = currentContext.apiEnvironment.layer;
apiEnvironment = [apiEnvironment withUpdatedLangPackCode:currentContext.apiEnvironment.langPackCode];
apiEnvironment.disableUpdates = true;
apiEnvironment.langPack = currentContext.apiEnvironment.langPack;
MTContext *context = [[MTContext alloc] initWithSerialization:currentContext.serialization apiEnvironment:apiEnvironment];
if (datacenterId != 0) {
context.keychain = currentContext.keychain;
}
MTProto *mtProto = [[MTProto alloc] initWithContext:context datacenterId:datacenterId usageCalculationInfo:nil];
if (datacenterId != 0) {
mtProto.useTempAuthKeys = true;
}
MTRequestMessageService *requestService = [[MTRequestMessageService alloc] initWithContext:context];
[mtProto addMessageService:requestService];
[mtProto resume];
MTRequest *request = [[MTRequest alloc] init];
NSData *getConfigData = nil;
MTRequestDatacenterAddressListParser responseParser = [currentContext.serialization requestDatacenterAddressWithData:&getConfigData];
[request setPayload:getConfigData metadata:@"getConfig" responseParser:responseParser];
__weak MTContext *weakCurrentContext = currentContext;
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
[request setCompleted:^(MTDatacenterAddressListData *result, __unused NSTimeInterval completionTimestamp, id error)
{
if (error == nil) {
__strong MTContext *strongCurrentContext = weakCurrentContext;
if (strongCurrentContext != nil) {
[result.addressList enumerateKeysAndObjectsUsingBlock:^(NSNumber *nDatacenterId, NSArray *list, __unused BOOL *stop) {
MTDatacenterAddressSet *addressSet = [[MTDatacenterAddressSet alloc] initWithAddressList:list];
MTDatacenterAddressSet *currentAddressSet = [context addressSetForDatacenterWithId:[nDatacenterId integerValue]];
if (currentAddressSet == nil || ![addressSet isEqual:currentAddressSet])
{
if (MTLogEnabled()) {
MTLog(@"[Backup address fetch: updating datacenter %d address set to %@]", [nDatacenterId intValue], addressSet);
}
[strongCurrentContext updateAddressSetForDatacenterWithId:[nDatacenterId integerValue] addressSet:addressSet forceUpdateSchemes:true];
[subscriber putNext:@true];
[subscriber putCompletion];
}
}];
}
} else {
[subscriber putCompletion];
}
}];
[requestService addRequest:request];
id requestId = request.internalId;
return [[MTBlockDisposable alloc] initWithBlock:^{
[requestService removeRequestByInternalId:requestId];
[mtProto pause];
}];
}];
}
@@ -127,77 +211,17 @@
return [[[MTSignal mergeSignals:signals] take:1] mapToSignal:^MTSignal *(MTBackupDatacenterData *data) {
if (data != nil && data.addressList.count != 0) {
MTApiEnvironment *apiEnvironment = [currentContext.apiEnvironment copy];
NSMutableDictionary *datacenterAddressOverrides = [[NSMutableDictionary alloc] init];
MTBackupDatacenterAddress *address = data.addressList[0];
datacenterAddressOverrides[@(data.datacenterId)] = [[MTDatacenterAddress alloc] initWithIp:address.ip port:(uint16_t)address.port preferForMedia:false restrictToTcp:false cdn:false preferForProxy:false secret:nil];
apiEnvironment.datacenterAddressOverrides = datacenterAddressOverrides;
apiEnvironment.apiId = currentContext.apiEnvironment.apiId;
apiEnvironment.layer = currentContext.apiEnvironment.layer;
apiEnvironment = [apiEnvironment withUpdatedLangPackCode:currentContext.apiEnvironment.langPackCode];
apiEnvironment.disableUpdates = true;
apiEnvironment.langPack = currentContext.apiEnvironment.langPack;
MTContext *context = [[MTContext alloc] initWithSerialization:currentContext.serialization apiEnvironment:apiEnvironment];
if (data.datacenterId != 0) {
context.keychain = currentContext.keychain;
NSMutableArray *signals = [[NSMutableArray alloc] init];
NSTimeInterval delay = 0.0;
for (MTBackupDatacenterAddress *address in data.addressList) {
MTSignal *signal = [self fetchConfigFromAddress:address datacenterId:data.datacenterId currentContext:currentContext];
if (delay > DBL_EPSILON) {
signal = [signal delay:delay onQueue:[[MTQueue alloc] init]];
}
[signals addObject:signal];
delay += 5.0;
}
MTProto *mtProto = [[MTProto alloc] initWithContext:context datacenterId:data.datacenterId usageCalculationInfo:nil];
if (data.datacenterId != 0) {
mtProto.useTempAuthKeys = true;
}
MTRequestMessageService *requestService = [[MTRequestMessageService alloc] initWithContext:context];
[mtProto addMessageService:requestService];
[mtProto resume];
MTRequest *request = [[MTRequest alloc] init];
NSData *getConfigData = nil;
MTRequestDatacenterAddressListParser responseParser = [currentContext.serialization requestDatacenterAddressWithData:&getConfigData];
[request setPayload:getConfigData metadata:@"getConfig" responseParser:responseParser];
__weak MTContext *weakCurrentContext = currentContext;
return [[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
[request setCompleted:^(MTDatacenterAddressListData *result, __unused NSTimeInterval completionTimestamp, id error)
{
if (error == nil) {
__strong MTContext *strongCurrentContext = weakCurrentContext;
if (strongCurrentContext != nil) {
[result.addressList enumerateKeysAndObjectsUsingBlock:^(NSNumber *nDatacenterId, NSArray *list, __unused BOOL *stop) {
MTDatacenterAddressSet *addressSet = [[MTDatacenterAddressSet alloc] initWithAddressList:list];
MTDatacenterAddressSet *currentAddressSet = [context addressSetForDatacenterWithId:[nDatacenterId integerValue]];
if (currentAddressSet == nil || ![addressSet isEqual:currentAddressSet])
{
if (MTLogEnabled()) {
MTLog(@"[Backup address fetch (%@): updating datacenter %d address set to %@]", isTestingEnvironment ? @"testing" : @"production", [nDatacenterId intValue], addressSet);
}
[strongCurrentContext updateAddressSetForDatacenterWithId:[nDatacenterId integerValue] addressSet:addressSet forceUpdateSchemes:true];
}
}];
}
} else {
[subscriber putCompletion];
}
}];
[requestService addRequest:request];
id requestId = request.internalId;
return [[MTBlockDisposable alloc] initWithBlock:^{
[requestService removeRequestByInternalId:requestId];
[mtProto pause];
}];
}];
return [[MTSignal mergeSignals:signals] take:1];
}
return [MTSignal complete];
}];

View File

@@ -1121,13 +1121,21 @@
{
[[MTContext contextQueue] dispatchOnQueue:^
{
for (NSNumber *nDatacenterId in _datacenterAuthActions)
{
if (_datacenterAuthActions[nDatacenterId] == action)
{
[_datacenterAuthActions removeObjectForKey:nDatacenterId];
break;
if (action.tempAuth) {
for (NSNumber *nDatacenterId in _datacenterTempAuthActions) {
if (_datacenterTempAuthActions[nDatacenterId] == action) {
[_datacenterTempAuthActions removeObjectForKey:nDatacenterId];
break;
}
}
} else {
for (NSNumber *nDatacenterId in _datacenterAuthActions) {
if (_datacenterAuthActions[nDatacenterId] == action) {
[_datacenterAuthActions removeObjectForKey:nDatacenterId];
break;
}
}
}
}];

View File

@@ -19,6 +19,7 @@
@interface MTDatacenterAuthAction : NSObject
@property (nonatomic, readonly) bool tempAuth;
@property (nonatomic, weak) id<MTDatacenterAuthActionDelegate> delegate;
- (instancetype)initWithTempAuth:(bool)tempAuth tempAuthKeyType:(MTDatacenterAuthTempKeyType)tempAuthKeyType;

View File

@@ -13,7 +13,6 @@
@interface MTDatacenterAuthAction () <MTDatacenterAuthMessageServiceDelegate>
{
bool _tempAuth;
MTDatacenterAuthTempKeyType _tempAuthKeyType;
NSInteger _datacenterId;

View File

@@ -1983,33 +1983,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}
if (protocolErrorCode == -404) {
if (_cdn) {
_authInfo = nil;
[_context performBatchUpdates:^{
[_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil];
[_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:true];
}];
_mtState |= MTProtoStateAwaitingDatacenterAuthorization;
} else if (_useTempAuthKeys) {
MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain;
if (transport.address.preferForMedia) {
tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia;
}
MTDatacenterAuthKey *currentTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType];
_authInfo = [_authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:nil];
_mtState |= MTProtoStateAwaitingDatacenterTempAuthKey;
[_context performBatchUpdates:^{
MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId];
if ([authInfo tempAuthKeyWithType:tempAuthKeyType].authKeyId == currentTempAuthKey.authKeyId) {
authInfo = [authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:nil];
[_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo];
[_context tempAuthKeyForDatacenterWithIdRequired:_datacenterId keyType:tempAuthKeyType];
}
}];
}
[self handleMissingKey:transport.address];
}
if (currentTransport == _transport)
@@ -2033,8 +2007,25 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
int64_t dataMessageId = 0;
bool parseError = false;
NSArray *parsedMessages = [self _parseIncomingMessages:decryptedData dataMessageId:&dataMessageId parseError:&parseError];
if (parseError)
{
for (MTIncomingMessage *message in parsedMessages) {
if ([message.body isKindOfClass:[MTRpcResultMessage class]]) {
MTRpcResultMessage *rpcResultMessage = message.body;
id maybeInternalMessage = [MTInternalMessageParser parseMessage:rpcResultMessage.data];
if ([maybeInternalMessage isKindOfClass:[MTRpcError class]]) {
MTRpcError *rpcError = maybeInternalMessage;
if (rpcError.errorCode == 401 && [rpcError.errorDescription isEqualToString:@"AUTH_KEY_PERM_EMPTY"]) {
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p received AUTH_KEY_PERM_EMPTY]", self);
}
[self handleMissingKey:transport.address];
[self requestSecureTransportReset];
return;
}
}
}
}
if (parseError) {
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p incoming data parse error]", self);
}
@@ -2042,9 +2033,7 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
[self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]];
[self resetSessionInfo];
}
else
{
} else {
[self transportTransactionsSucceeded:@[transactionId]];
for (MTIncomingMessage *incomingMessage in parsedMessages)
@@ -2071,6 +2060,38 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
}
}];
}
- (void)handleMissingKey:(MTDatacenterAddress *)address {
NSAssert([[MTProto managerQueue] isCurrentQueue], @"invalid queue");
if (_cdn) {
_authInfo = nil;
[_context performBatchUpdates:^{
[_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:nil];
[_context authInfoForDatacenterWithIdRequired:_datacenterId isCdn:true];
}];
_mtState |= MTProtoStateAwaitingDatacenterAuthorization;
} else if (_useTempAuthKeys) {
MTDatacenterAuthTempKeyType tempAuthKeyType = MTDatacenterAuthTempKeyTypeMain;
if (address.preferForMedia) {
tempAuthKeyType = MTDatacenterAuthTempKeyTypeMedia;
}
MTDatacenterAuthKey *currentTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType];
_authInfo = [_authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:nil];
_mtState |= MTProtoStateAwaitingDatacenterTempAuthKey;
[_context performBatchUpdates:^{
MTDatacenterAuthInfo *authInfo = [_context authInfoForDatacenterWithId:_datacenterId];
if ([authInfo tempAuthKeyWithType:tempAuthKeyType].authKeyId == currentTempAuthKey.authKeyId) {
authInfo = [authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:nil];
[_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:authInfo];
[_context tempAuthKeyForDatacenterWithIdRequired:_datacenterId keyType:tempAuthKeyType];
}
}];
}
}
- (NSData *)_decryptIncomingTransportData:(NSData *)data address:(MTDatacenterAddress *)address
{
@@ -2544,8 +2565,12 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
MTDatacenterAuthKey *effectiveTempAuthKey = [_authInfo tempAuthKeyWithType:tempAuthKeyType];
if (effectiveTempAuthKey != nil) {
_authInfo = [_authInfo withUpdatedTempAuthKeyWithType:tempAuthKeyType key:[[MTDatacenterAuthKey alloc] initWithAuthKey:effectiveTempAuthKey.authKey authKeyId:effectiveTempAuthKey.authKeyId notBound:false]];
NSMutableDictionary *authKeyAttributes = [[NSMutableDictionary alloc] initWithDictionary:_authInfo.authKeyAttributes];
[authKeyAttributes removeObjectForKey:@"apiInitializationHash"];
_authInfo = [_authInfo withUpdatedAuthKeyAttributes:authKeyAttributes];
[_context updateAuthInfoForDatacenterWithId:_datacenterId authInfo:_authInfo];
}
_bindingTempAuthKeyId = 0;
if ((_mtState & MTProtoStateBindingTempAuthKey) != 0) {
[self setMtState:_mtState & (~MTProtoStateBindingTempAuthKey)];
[self requestTransportTransaction];
@@ -2554,6 +2579,8 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
if (MTLogEnabled()) {
MTLog(@"[MTProto#%p bindTempAuthKey error %@]", self, rpcError);
}
[self requestTransportTransaction];
}
}
}

View File

@@ -29,7 +29,7 @@
#import "MTDNS.h"
#import "MTSignal.h"
#define MT_TCPO25 0
#define MT_TCPO25 1
MTInternalIdClass(MTTcpConnection)
@@ -428,8 +428,8 @@ struct ctr_state {
if (useEncryption) {
int32_t controlVersion = 0xefefefef;
memcpy(controlBytes + 56, &controlVersion, 4);
int32_t datacenterTag = _datacenterTag;
memcpy(controlBytes + 60, &datacenterTag, 4);
int16_t datacenterTag = (int16_t)_datacenterTag;
memcpy(controlBytes + 60, &datacenterTag, 2);
uint8_t controlBytesReversed[64];
for (int i = 0; i < 64; i++) {
@@ -452,6 +452,16 @@ struct ctr_state {
}
NSData *aesKeyHash = MTSha256(aesKeyData);
aesKey = [aesKeyHash subdataWithRange:NSMakeRange(0, 32)];
NSMutableData *incomingAesKeyData = [[NSMutableData alloc] init];
[incomingAesKeyData appendData:incomingAesKey];
if (_mtpSecret != nil) {
[incomingAesKeyData appendData:_mtpSecret];
} else if (_address.secret != nil) {
[incomingAesKeyData appendData:_address.secret];
}
NSData *incomingAesKeyHash = MTSha256(incomingAesKeyData);
incomingAesKey = [incomingAesKeyHash subdataWithRange:NSMakeRange(0, 32)];
}
#endif