Move UD auth into request initializers

pull/1/head
Michael Kirk 7 years ago
parent 39ba413439
commit 0be1f8cca2

@ -56,6 +56,11 @@ public class ProfileFetcherJob: NSObject {
return SSKEnvironment.shared.identityManager
}
private var signalServiceClient: SignalServiceClient {
// TODO hang on SSKEnvironment
return SignalServiceRestClient()
}
// MARK: -
public func run(recipientIds: [String]) {
@ -88,8 +93,7 @@ public class ProfileFetcherJob: NSObject {
}
enum ProfileFetcherJobError: Error {
case throttled(lastTimeInterval: TimeInterval),
unknownNetworkError
case throttled(lastTimeInterval: TimeInterval)
}
public func updateProfile(recipientId: String, remainingRetries: Int = 3) {
@ -130,12 +134,11 @@ public class ProfileFetcherJob: NSObject {
Logger.error("getProfile: \(recipientId)")
let request = OWSRequestFactory.getProfileRequest(withRecipientId: recipientId)
let (promise, fulfill, reject) = Promise<SignalServiceProfile>.pending()
// TODO: Use UD socket for some profile gets.
if socketManager.canMakeRequests(of: .default) {
let request = OWSRequestFactory.getProfileRequest(recipientId: recipientId, unidentifiedAccess: nil)
let (promise, fulfill, reject) = Promise<SignalServiceProfile>.pending()
self.socketManager.make(request,
webSocketType: .default,
success: { (responseObject: Any?) -> Void in
@ -149,27 +152,11 @@ public class ProfileFetcherJob: NSObject {
failure: { (_: NSInteger, _:Data?, error: Error) in
reject(error)
})
return promise
} else {
self.networkManager.makeRequest(request,
success: { (_: URLSessionDataTask?, responseObject: Any?) -> Void in
do {
let profile = try SignalServiceProfile(recipientId: recipientId, responseObject: responseObject)
fulfill(profile)
} catch {
reject(error)
}
},
failure: { (_: URLSessionDataTask?, error: Error?) in
if let error = error {
reject(error)
}
reject(ProfileFetcherJobError.unknownNetworkError)
})
// TODO unidentified AUTH
return self.signalServiceClient.retrieveProfile(recipientId: recipientId, unidentifiedAccess: nil)
}
return promise
}
private func updateProfile(signalServiceProfile: SignalServiceProfile) {
@ -221,45 +208,3 @@ public class ProfileFetcherJob: NSObject {
}
}
}
@objc
public class SignalServiceProfile: NSObject {
public enum ValidationError: Error {
case invalid(description: String)
case invalidIdentityKey(description: String)
case invalidProfileName(description: String)
}
public let recipientId: String
public let identityKey: Data
public let profileNameEncrypted: Data?
public let avatarUrlPath: String?
public let unidentifiedAccessVerifier: Data?
public let hasUnrestrictedUnidentifiedAccess: Bool
init(recipientId: String, responseObject: Any?) throws {
self.recipientId = recipientId
guard let params = ParamParser(responseObject: responseObject) else {
throw ValidationError.invalid(description: "invalid response: \(String(describing: responseObject))")
}
let identityKeyWithType = try params.requiredBase64EncodedData(key: "identityKey")
let kIdentityKeyLength = 33
guard identityKeyWithType.count == kIdentityKeyLength else {
throw ValidationError.invalidIdentityKey(description: "malformed identity key \(identityKeyWithType.hexadecimalString) with decoded length: \(identityKeyWithType.count)")
}
// `removeKeyType` is an objc category method only on NSData, so temporarily cast.
self.identityKey = (identityKeyWithType as NSData).removeKeyType() as Data
self.profileNameEncrypted = try params.optionalBase64EncodedData(key: "name")
let avatarUrlPath: String? = try params.optional(key: "avatar")
self.avatarUrlPath = avatarUrlPath
self.unidentifiedAccessVerifier = try params.optionalBase64EncodedData(key: "unidentifiedAccess")
self.hasUnrestrictedUnidentifiedAccess = try params.optional(key: "unrestrictedUnidentifiedAccess") ?? false
}
}

@ -36,7 +36,7 @@ public class OWSMessageSend: NSObject {
public var hasUDAuthFailed = false
@objc
public let udAccessKey: SMKUDAccessKey?
public let unidentifiedAccess: SSKUnidentifiedAccess?
@objc
public let localNumber: String
@ -44,9 +44,6 @@ public class OWSMessageSend: NSObject {
@objc
public let isLocalNumber: Bool
@objc
public let senderCertificate: SMKSenderCertificate?
@objc
public let success: () -> Void
@ -65,10 +62,11 @@ public class OWSMessageSend: NSObject {
self.message = message
self.thread = thread
self.recipient = recipient
self.senderCertificate = senderCertificate
var udAccessKey: SMKUDAccessKey?
var isLocalNumber: Bool = false
let senderCertificate = senderCertificate
let udAccessKey: SMKUDAccessKey?
var isLocalNumber: Bool
if let recipientId = recipient.uniqueId {
switch udManager.unidentifiedAccessMode(recipientId: recipientId) {
case .enabled:
@ -80,9 +78,16 @@ public class OWSMessageSend: NSObject {
}
isLocalNumber = localNumber == recipientId
} else {
isLocalNumber = false
udAccessKey = nil
owsFailDebug("SignalRecipient missing recipientId")
}
self.udAccessKey = udAccessKey
if let udAccessKey = udAccessKey, let senderCertificate = senderCertificate {
self.unidentifiedAccess = SSKUnidentifiedAccess(accessKey: udAccessKey, senderCertificate: senderCertificate)
} else {
self.unidentifiedAccess = nil
}
self.localNumber = localNumber
self.isLocalNumber = isLocalNumber
@ -92,6 +97,6 @@ public class OWSMessageSend: NSObject {
@objc
public var isUDSend: Bool {
return (!hasUDAuthFailed && udAccessKey != nil && senderCertificate != nil)
return (!hasUDAuthFailed && self.unidentifiedAccess != nil)
}
}

@ -998,12 +998,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
TSRequest *request = [OWSRequestFactory submitMessageRequestWithRecipient:recipient.uniqueId
messages:deviceMessages
timeStamp:message.timestamp];
if (messageSend.isUDSend) {
DDLogVerbose(@"UD send.");
[request useUDAuth:messageSend.udAccessKey];
}
timeStamp:message.timestamp
unidentifiedAccess:messageSend.unidentifiedAccess];
OWSWebSocketType webSocketType = (messageSend.isUDSend ? OWSWebSocketTypeUD : OWSWebSocketTypeDefault);
BOOL canMakeWebsocketRequests = ([TSSocketManager.shared canMakeRequestsOfType:webSocketType] &&
@ -1090,7 +1086,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[SignalRecipient markRecipientAsRegisteredAndGet:recipient.recipientId transaction:transaction];
}];
[self handleMessageSentLocally:messageSend.message senderCertificate:messageSend.senderCertificate];
[self handleMessageSentLocally:messageSend.message
senderCertificate:messageSend.unidentifiedAccess.senderCertificate];
messageSend.success();
});
}
@ -1399,13 +1396,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// To avoid deadlock, we need to ensure that our success/failure completions
// are called _off_ the main thread. Otherwise we'll deadlock if the main
// thread is blocked on opening a transaction.
TSRequest *request =
[OWSRequestFactory recipientPrekeyRequestWithRecipient:recipientId deviceId:[deviceId stringValue]];
if (messageSend.isUDSend) {
DDLogVerbose(@"UD prekey request.");
[request useUDAuth:messageSend.udAccessKey];
}
TSRequest *request = [OWSRequestFactory recipientPrekeyRequestWithRecipient:recipientId
deviceId:[deviceId stringValue]
unidentifiedAccess:messageSend.unidentifiedAccess];
[self.networkManager makeRequest:request
completionQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
@ -1509,7 +1502,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
serializedMessage = [secretCipher encryptMessageWithRecipientId:recipientId
deviceId:deviceId.intValue
paddedPlaintext:[plainText paddedMessageBody]
senderCertificate:messageSend.senderCertificate
senderCertificate:messageSend.unidentifiedAccess.senderCertificate
protocolContext:transaction
error:&error];
messageType = TSUnidentifiedSenderMessageType;

@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ECKeyPair;
@class OWSDevice;
@class PreKeyRecord;
@class SSKUnidentifiedAccess;
@class SignedPreKeyRecord;
@class TSRequest;
@ -35,7 +36,9 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)getMessagesRequest;
+ (TSRequest *)getProfileRequestWithRecipientId:(NSString *)recipientId;
+ (TSRequest *)getProfileRequestWithRecipientId:(NSString *)recipientId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess
NS_SWIFT_NAME(getProfileRequest(recipientId:unidentifiedAccess:));
+ (TSRequest *)turnServerInfoRequest;
@ -58,7 +61,8 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
timeStamp:(uint64_t)timeStamp;
timeStamp:(uint64_t)timeStamp
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess;
+ (TSRequest *)verifyCodeRequestWithVerificationCode:(NSString *)verificationCode
forNumber:(NSString *)phoneNumber
@ -72,7 +76,9 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)currentSignedPreKeyRequest;
+ (TSRequest *)recipientPrekeyRequestWithRecipient:(NSString *)recipientNumber deviceId:(NSString *)deviceId;
+ (TSRequest *)recipientPrekeyRequestWithRecipient:(NSString *)recipientNumber
deviceId:(NSString *)deviceId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess;
+ (TSRequest *)registerSignedPrekeyRequestWithSignedPreKeyRecord:(SignedPreKeyRecord *)signedPreKey;

@ -124,11 +124,16 @@ NS_ASSUME_NONNULL_BEGIN
}
+ (TSRequest *)getProfileRequestWithRecipientId:(NSString *)recipientId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess
{
OWSAssertDebug(recipientId.length > 0);
NSString *path = [NSString stringWithFormat:textSecureProfileAPIFormat, recipientId];
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
if (unidentifiedAccess != nil) {
[request useUDAuthWithAccessKey:unidentifiedAccess.accessKey];
}
return request;
}
+ (TSRequest *)turnServerInfoRequest
@ -181,13 +186,20 @@ NS_ASSUME_NONNULL_BEGIN
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
}
+ (TSRequest *)recipientPrekeyRequestWithRecipient:(NSString *)recipientNumber deviceId:(NSString *)deviceId
+ (TSRequest *)recipientPrekeyRequestWithRecipient:(NSString *)recipientNumber
deviceId:(NSString *)deviceId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess;
{
OWSAssertDebug(recipientNumber.length > 0);
OWSAssertDebug(deviceId.length > 0);
NSString *path = [NSString stringWithFormat:@"%@/%@/%@", textSecureKeysAPI, recipientNumber, deviceId];
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
if (unidentifiedAccess != nil) {
[request useUDAuthWithAccessKey:unidentifiedAccess.accessKey];
}
return request;
}
+ (TSRequest *)registerForPushRequestWithPushIdentifier:(NSString *)identifier voipIdentifier:(NSString *)voipId
@ -316,6 +328,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
timeStamp:(uint64_t)timeStamp
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess
{
// NOTE: messages may be empty; See comments in OWSDeviceManager.
OWSAssertDebug(recipientId.length > 0);
@ -327,7 +340,11 @@ NS_ASSUME_NONNULL_BEGIN
@"timestamp" : @(timeStamp),
};
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters];
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters];
if (unidentifiedAccess != nil) {
[request useUDAuthWithAccessKey:unidentifiedAccess.accessKey];
}
return request;
}
+ (TSRequest *)registerSignedPrekeyRequestWithSignedPreKeyRecord:(SignedPreKeyRecord *)signedPreKey

@ -30,6 +30,6 @@
#pragma mark - UD
- (void)useUDAuth:(SMKUDAccessKey *)udAccessKey;
- (void)useUDAuthWithAccessKey:(SMKUDAccessKey *)udAccessKey;
@end

@ -114,7 +114,7 @@
#pragma mark - UD
- (void)useUDAuth:(SMKUDAccessKey *)udAccessKey
- (void)useUDAuthWithAccessKey:(SMKUDAccessKey *)udAccessKey
{
OWSAssertDebug(udAccessKey);

@ -0,0 +1,47 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public class SignalServiceProfile: NSObject {
public enum ValidationError: Error {
case invalid(description: String)
case invalidIdentityKey(description: String)
case invalidProfileName(description: String)
}
public let recipientId: String
public let identityKey: Data
public let profileNameEncrypted: Data?
public let avatarUrlPath: String?
public let unidentifiedAccessVerifier: Data?
public let hasUnrestrictedUnidentifiedAccess: Bool
public init(recipientId: String, responseObject: Any?) throws {
self.recipientId = recipientId
guard let params = ParamParser(responseObject: responseObject) else {
throw ValidationError.invalid(description: "invalid response: \(String(describing: responseObject))")
}
let identityKeyWithType = try params.requiredBase64EncodedData(key: "identityKey")
let kIdentityKeyLength = 33
guard identityKeyWithType.count == kIdentityKeyLength else {
throw ValidationError.invalidIdentityKey(description: "malformed identity key \(identityKeyWithType.hexadecimalString) with decoded length: \(identityKeyWithType.count)")
}
// `removeKeyType` is an objc category method only on NSData, so temporarily cast.
self.identityKey = (identityKeyWithType as NSData).removeKeyType() as Data
self.profileNameEncrypted = try params.optionalBase64EncodedData(key: "name")
let avatarUrlPath: String? = try params.optional(key: "avatar")
self.avatarUrlPath = avatarUrlPath
self.unidentifiedAccessVerifier = try params.optionalBase64EncodedData(key: "unidentifiedAccess")
self.hasUnrestrictedUnidentifiedAccess = try params.optional(key: "unrestrictedUnidentifiedAccess") ?? false
}
}

@ -4,13 +4,31 @@
import Foundation
import PromiseKit
import SignalMetadataKit
protocol SignalServiceClient {
public typealias RecipientIdentifier = String
@objc
public class SSKUnidentifiedAccess: NSObject {
@objc
let accessKey: SMKUDAccessKey
@objc
let senderCertificate: SMKSenderCertificate
init(accessKey: SMKUDAccessKey, senderCertificate: SMKSenderCertificate) {
self.accessKey = accessKey
self.senderCertificate = senderCertificate
}
}
public protocol SignalServiceClient {
func getAvailablePreKeys() -> Promise<Int>
func registerPreKeys(identityKey: IdentityKey, signedPreKeyRecord: SignedPreKeyRecord, preKeyRecords: [PreKeyRecord]) -> Promise<Void>
func setCurrentSignedPreKey(_ signedPreKey: SignedPreKeyRecord) -> Promise<Void>
func requestUDSenderCertificate() -> Promise<Data>
func updateAcountAttributes() -> Promise<Void>
func retrieveProfile(recipientId: RecipientIdentifier, unidentifiedAccess: SSKUnidentifiedAccess?) -> Promise<SignalServiceProfile>
}
/// Based on libsignal-service-java's PushServiceSocket class
@ -25,7 +43,7 @@ public class SignalServiceRestClient: NSObject, SignalServiceClient {
return OWSErrorMakeUnableToProcessServerResponseError()
}
func getAvailablePreKeys() -> Promise<Int> {
public func getAvailablePreKeys() -> Promise<Int> {
Logger.debug("")
let request = OWSRequestFactory.availablePreKeysCountRequest()
@ -41,7 +59,7 @@ public class SignalServiceRestClient: NSObject, SignalServiceClient {
}
}
func registerPreKeys(identityKey: IdentityKey, signedPreKeyRecord: SignedPreKeyRecord, preKeyRecords: [PreKeyRecord]) -> Promise<Void> {
public func registerPreKeys(identityKey: IdentityKey, signedPreKeyRecord: SignedPreKeyRecord, preKeyRecords: [PreKeyRecord]) -> Promise<Void> {
Logger.debug("")
let request = OWSRequestFactory.registerPrekeysRequest(withPrekeyArray: preKeyRecords, identityKey: identityKey, signedPreKey: signedPreKeyRecord)
@ -83,4 +101,11 @@ public class SignalServiceRestClient: NSObject, SignalServiceClient {
})
return promise
}
public func retrieveProfile(recipientId: RecipientIdentifier, unidentifiedAccess: SSKUnidentifiedAccess?) -> Promise<SignalServiceProfile> {
let request = OWSRequestFactory.getProfileRequest(recipientId: recipientId, unidentifiedAccess: unidentifiedAccess)
return networkManager.makePromise(request: request).then { (task: URLSessionDataTask, responseObject: Any?) in
return try SignalServiceProfile(recipientId: recipientId, responseObject: responseObject)
}
}
}

Loading…
Cancel
Save