212 lines
8.0 KiB
Objective-C
212 lines
8.0 KiB
Objective-C
//
|
|
// RedPhoneAPICall.m
|
|
// Signal
|
|
//
|
|
// Created by Frederic Jacobs on 05/10/14.
|
|
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
#import <SignalServiceKit/TSAccountManager.h>
|
|
#import "Constraints.h"
|
|
#import "CryptoTools.h"
|
|
#import "PhoneNumber.h"
|
|
#import "RPAPICall.h"
|
|
#import "SignalKeyingStorage.h"
|
|
#import "Util.h"
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
#define CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL 1
|
|
|
|
|
|
NSString *const RPAPICallPushTokenKey = @"apnRegistrationId";
|
|
NSString *const RPAPICallVoipTokenKey = @"voipRegistrationId";
|
|
NSString *const RPAPICallSignalingKeyKey = @"signalingKey";
|
|
|
|
@interface RPAPICall ()
|
|
|
|
@property (nonatomic, readwrite) NSString *endPoint;
|
|
@property (nonatomic, readwrite) HTTPMethod method;
|
|
@property (nonatomic, readwrite) NSMutableDictionary *parameters;
|
|
@property (nonatomic, readwrite) AFHTTPRequestSerializer<AFURLRequestSerialization> *requestSerializer;
|
|
@property (nonatomic, readwrite) AFHTTPResponseSerializer<AFURLResponseSerialization> *responseSerializer;
|
|
|
|
@end
|
|
|
|
@implementation RPAPICall
|
|
|
|
+ (RPAPICall *)defaultAPICall {
|
|
RPAPICall *apiCall = [[RPAPICall alloc] init];
|
|
apiCall.parameters = [NSMutableDictionary new];
|
|
apiCall.requestSerializer = [self basicAuthenticationSerializer];
|
|
apiCall.responseSerializer = [AFHTTPResponseSerializer serializer];
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)verifyWithTSToken:(NSString *)tsToken signalingKey:(NSData *)signalingKey
|
|
{
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
|
|
apiCall.method = HTTP_PUT;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/api/v1/accounts/token/%@", tsToken];
|
|
apiCall.parameters[RPAPICallSignalingKeyKey] = [signalingKey encodedAsBase64];
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)registerPushNotificationWithPushToken:(NSString *)pushToken voipToken:(NSString *)voipToken
|
|
{
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = HTTP_PUT;
|
|
|
|
apiCall.parameters[RPAPICallPushTokenKey] = pushToken;
|
|
apiCall.parameters[RPAPICallVoipTokenKey] = voipToken;
|
|
apiCall.endPoint = @"/api/v1/accounts/apn";
|
|
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)unregisterWithPushToken:(NSData *)pushToken {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = HTTP_DELETE;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", pushToken.encodedAsHexString];
|
|
apiCall.requestSerializer = [self basicAuthenticationSerializer];
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)requestToOpenPortWithSessionId:(int64_t)sessionId {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = HTTP_GET;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/open/%lld", sessionId];
|
|
apiCall.requestSerializer = [self unauthenticatedSerializer];
|
|
apiCall.responseSerializer = [AFHTTPResponseSerializer serializer];
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)requestToRingWithSessionId:(int64_t)sessionId {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = SIGNAL_RING;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId];
|
|
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)requestToSignalBusyWithSessionId:(int64_t)sessionId {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = SIGNAL_BUSY;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId];
|
|
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)requestToInitiateToRemoteNumber:(PhoneNumber *)remoteNumber {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
|
|
ows_require(remoteNumber != nil);
|
|
|
|
NSString *formattedRemoteNumber = remoteNumber.toE164;
|
|
NSString *interopVersionInsert =
|
|
(CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0)
|
|
? @""
|
|
: [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL];
|
|
|
|
apiCall.method = HTTP_GET;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/session%@/%@", interopVersionInsert, formattedRemoteNumber];
|
|
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
|
return apiCall;
|
|
}
|
|
|
|
#pragma mark Authorization Headers
|
|
|
|
+ (AFHTTPRequestSerializer *)basicAuthenticationSerializer {
|
|
AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializerWithWritingOptions:0];
|
|
[serializer setValue:[self computeBasicAuthorizationTokenForLocalNumber:[TSAccountManager localNumber]
|
|
andPassword:SignalKeyingStorage.serverAuthPassword]
|
|
forHTTPHeaderField:@"Authorization"];
|
|
return serializer;
|
|
}
|
|
|
|
+ (AFHTTPRequestSerializer *)otpAuthenticationSerializer {
|
|
AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializerWithWritingOptions:0];
|
|
[serializer setValue:[self computeOtpAuthorizationTokenForLocalNumber:[TSAccountManager localNumber]
|
|
andCounterValue:[SignalKeyingStorage
|
|
getAndIncrementOneTimeCounter]
|
|
andPassword:SignalKeyingStorage.serverAuthPassword]
|
|
forHTTPHeaderField:@"Authorization"];
|
|
return serializer;
|
|
}
|
|
|
|
+ (AFHTTPRequestSerializer *)unauthenticatedSerializer {
|
|
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
|
|
return serializer;
|
|
}
|
|
|
|
+ (NSString *)computeOtpAuthorizationTokenForLocalNumber:(NSString *)localNumber
|
|
andCounterValue:(int64_t)counterValue
|
|
andPassword:(NSString *)password {
|
|
ows_require(localNumber != nil);
|
|
ows_require(password != nil);
|
|
|
|
NSString *rawToken =
|
|
[NSString stringWithFormat:@"%@:%@:%lld",
|
|
localNumber,
|
|
[CryptoTools computeOtpWithPassword:password andCounter:counterValue],
|
|
counterValue];
|
|
return [@"OTP " stringByAppendingString:rawToken.encodedAsUtf8.encodedAsBase64];
|
|
}
|
|
|
|
+ (NSString *)computeBasicAuthorizationTokenForLocalNumber:(NSString *)localNumber andPassword:(NSString *)password {
|
|
NSString *rawToken = [NSString stringWithFormat:@"%@:%@", localNumber, password];
|
|
return [@"Basic " stringByAppendingString:rawToken.encodedAsUtf8.encodedAsBase64];
|
|
}
|
|
|
|
/* <---> Registering with on RP server is soon going to be deprecated
|
|
|
|
+ (RPAPICall*)requestVerificationCode {
|
|
[SignalKeyingStorage generateServerAuthPassword];
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = HTTP_GET;
|
|
apiCall.endPoint = @"/users/verification/sms?client=ios";
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall*)requestVerificationCodeWithVoice {
|
|
RPAPICall *apiCall = [self requestVerificationCode];
|
|
apiCall.endPoint = @"/users/verification/voice?client=ios";
|
|
return apiCall;
|
|
}
|
|
|
|
|
|
|
|
+ (RPAPICall *)verifyVerificationCode:(NSString *)verificationCode {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
[SignalKeyingStorage generateSignaling];
|
|
apiCall.method = HTTP_PUT;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/%@", SignalKeyingStorage.localNumber];
|
|
|
|
NSData *signalingCipherKey = SignalKeyingStorage.signalingCipherKey;
|
|
NSData *signalingMacKey = SignalKeyingStorage.signalingMacKey;
|
|
NSData *signalingExtraKeyData = SignalKeyingStorage.signalingExtraKey;
|
|
NSString *encodedSignalingKey =
|
|
@[ signalingCipherKey, signalingMacKey, signalingExtraKeyData ].ows_concatDatas.encodedAsBase64;
|
|
apiCall.parameters = @{ @"key" : encodedSignalingKey, @"challenge" : verificationCode };
|
|
|
|
return apiCall;
|
|
}
|
|
|
|
+ (RPAPICall *)requestTextSecureVerificationCode {
|
|
RPAPICall *apiCall = [self defaultAPICall];
|
|
apiCall.method = HTTP_GET;
|
|
apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/textsecure"];
|
|
return apiCall;
|
|
}
|
|
*/
|
|
|
|
- (NSString *)description
|
|
{
|
|
return [NSString stringWithFormat:@"%@ %@", [super description], self.endPoint];
|
|
}
|
|
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|