Remove SSKUnidentifiedAccess.

pull/1/head
Matthew Chen 7 years ago
parent 5d18497ade
commit 7de289f6be

@ -5,6 +5,7 @@
import Foundation
import PromiseKit
import SignalServiceKit
import SignalMetadataKit
@objc
public class ProfileFetcherJob: NSObject {
@ -136,39 +137,47 @@ public class ProfileFetcherJob: NSObject {
// If we are in unknown mode, try using a random UD access key
// in case they support unrestricted access.
if self.udManager.unidentifiedAccessMode(recipientId: recipientId) == .unknown,
let randomUnidentifiedAccess = self.udManager.getRandomAccess() {
switch self.udManager.unidentifiedAccessMode(forRecipientId: recipientId) {
case .unknown, .unrestricted:
let randomUDAccessKey = self.udManager.randomUDAccessKey()
return requestProfile(recipientId: recipientId,
unidentifiedAccess: randomUnidentifiedAccess,
udAccessKey: randomUDAccessKey,
canFailoverUDAuth: false)
.recover { (_: Error) -> Promise<SignalServiceProfile> in
Logger.verbose("Failing over to non-random access.")
let unidentifiedAccess = self.getUnidentifiedAccess(forRecipientId: recipientId)
let udAccessKey = self.udManager.udAccessKey(forRecipientId: recipientId)
return self.requestProfile(recipientId: recipientId,
unidentifiedAccess: unidentifiedAccess,
udAccessKey: udAccessKey,
canFailoverUDAuth: true)
}
} else {
let unidentifiedAccess = getUnidentifiedAccess(forRecipientId: recipientId)
break
case .disabled:
return requestProfile(recipientId: recipientId,
unidentifiedAccess: unidentifiedAccess,
udAccessKey: nil,
canFailoverUDAuth: true)
break
case .enabled:
let udAccessKey = udManager.udAccessKey(forRecipientId: recipientId)
return requestProfile(recipientId: recipientId,
udAccessKey: udAccessKey,
canFailoverUDAuth: true)
break
}
}
private func requestProfile(recipientId: String,
unidentifiedAccess: SSKUnidentifiedAccess?,
udAccessKey: SMKUDAccessKey?,
canFailoverUDAuth: Bool) -> Promise<SignalServiceProfile> {
AssertIsOnMainThread()
let requestMaker = RequestMaker(requestFactoryBlock: { (unidentifiedAccessForRequest) -> TSRequest in
return OWSRequestFactory.getProfileRequest(recipientId: recipientId, unidentifiedAccess: unidentifiedAccessForRequest)
let requestMaker = RequestMaker(requestFactoryBlock: { (udAccessKeyForRequest) -> TSRequest in
return OWSRequestFactory.getProfileRequest(recipientId: recipientId, udAccessKey: udAccessKeyForRequest)
}, udAuthFailureBlock: {
// Do nothing
}, websocketFailureBlock: {
// Do nothing
}, recipientId: recipientId,
unidentifiedAccess: unidentifiedAccess,
udAccessKey: udAccessKey,
canFailoverUDAuth: canFailoverUDAuth)
return requestMaker.makeRequest()
.map { (result: RequestMakerResult) -> SignalServiceProfile in
@ -202,7 +211,7 @@ public class ProfileFetcherJob: NSObject {
return
}
guard let udAccessKey = udManager.rawUDAccessKeyForRecipient(recipientId) else {
guard let udAccessKey = udManager.udAccessKey(forRecipientId: recipientId) else {
udManager.setUnidentifiedAccessMode(.disabled, recipientId: recipientId)
return
}
@ -233,8 +242,4 @@ public class ProfileFetcherJob: NSObject {
}
}
}
private func getUnidentifiedAccess(forRecipientId recipientId: RecipientIdentifier) -> SSKUnidentifiedAccess? {
return self.udManager.getAccess(forRecipientId: recipientId)
}
}

@ -32,7 +32,10 @@ public class OWSMessageSend: NSObject {
public var hasWebsocketSendFailed = false
@objc
public var unidentifiedAccess: SSKUnidentifiedAccess?
public var udAccessKey: SMKUDAccessKey?
@objc
public var senderCertificate: SMKSenderCertificate?
@objc
public let localNumber: String
@ -59,14 +62,22 @@ public class OWSMessageSend: NSObject {
self.thread = thread
self.recipient = recipient
self.localNumber = localNumber
self.senderCertificate = senderCertificate
if let recipientId = recipient.uniqueId {
self.unidentifiedAccess = udManager.getAccess(forRecipientId: recipientId)
if senderCertificate != nil {
let accessMode = udManager.unidentifiedAccessMode(forRecipientId: recipientId)
if accessMode == .unrestricted {
self.udAccessKey = udManager.randomUDAccessKey()
} else if accessMode == .unrestricted {
self.udAccessKey = udManager.udAccessKey(forRecipientId: recipientId)
}
}
self.isLocalNumber = localNumber == recipientId
} else {
owsFailDebug("SignalRecipient missing recipientId")
self.isLocalNumber = false
self.unidentifiedAccess = nil
}
self.success = success
@ -75,12 +86,12 @@ public class OWSMessageSend: NSObject {
@objc
public var isUDSend: Bool {
return self.unidentifiedAccess != nil
return udAccessKey != nil && senderCertificate != nil
}
@objc
public func disableUD() {
unidentifiedAccess = nil
udAccessKey = nil
}
@objc

@ -1061,16 +1061,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSLogWarn(@"Sending a message with no device messages.");
}
OWSLogVerbose(@"Sending message; ud? %d %d.", messageSend.isUDSend, messageSend.unidentifiedAccess != nil);
OWSLogVerbose(@"Sending message; ud? %d %d.", messageSend.isUDSend, messageSend.udAccessKey != nil);
// NOTE: canFailoverUDAuth is NO because UD-auth and Non-UD-auth requests
// use different device lists.
OWSRequestMaker *requestMaker = [[OWSRequestMaker alloc]
initWithRequestFactoryBlock:^(SSKUnidentifiedAccess *_Nullable unidentifiedAccess) {
initWithRequestFactoryBlock:^(SMKUDAccessKey *_Nullable udAccessKey) {
return [OWSRequestFactory submitMessageRequestWithRecipient:recipient.recipientId
messages:deviceMessages
timeStamp:message.timestamp
unidentifiedAccess:unidentifiedAccess];
udAccessKey:udAccessKey];
}
udAuthFailureBlock:^{
[messageSend setHasUDAuthFailed];
@ -1079,7 +1079,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
messageSend.hasWebsocketSendFailed = YES;
}
recipientId:recipient.recipientId
unidentifiedAccess:messageSend.unidentifiedAccess
udAccessKey:messageSend.udAccessKey
canFailoverUDAuth:NO];
[[requestMaker makeRequestObjc]
.then(^(OWSRequestMakerResult *result) {
@ -1559,10 +1559,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
OWSAssertDebug(recipientId.length > 0);
OWSRequestMaker *requestMaker = [[OWSRequestMaker alloc]
initWithRequestFactoryBlock:^(SSKUnidentifiedAccess *_Nullable unidentifiedAccess) {
initWithRequestFactoryBlock:^(SMKUDAccessKey *_Nullable udAccessKey) {
return [OWSRequestFactory recipientPrekeyRequestWithRecipient:recipientId
deviceId:[deviceId stringValue]
unidentifiedAccess:unidentifiedAccess];
udAccessKey:udAccessKey];
}
udAuthFailureBlock:^{
[messageSend setHasUDAuthFailed];
@ -1571,7 +1571,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
messageSend.hasWebsocketSendFailed = YES;
}
recipientId:recipientId
unidentifiedAccess:messageSend.unidentifiedAccess
udAccessKey:messageSend.udAccessKey
canFailoverUDAuth:YES];
[[requestMaker makeRequestObjc]
.then(^(OWSRequestMakerResult *result) {
@ -1646,7 +1646,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
serializedMessage = [secretCipher encryptMessageWithRecipientId:recipientId
deviceId:deviceId.intValue
paddedPlaintext:[plainText paddedMessageBody]
senderCertificate:messageSend.unidentifiedAccess.senderCertificate
senderCertificate:messageSend.senderCertificate
protocolContext:transaction
error:&error];
messageType = TSUnidentifiedSenderMessageType;

@ -4,6 +4,7 @@
import Foundation
import PromiseKit
import SignalMetadataKit
@objc
public enum RequestMakerUDAuthError: Int, Error {
@ -36,7 +37,7 @@ public class RequestMakerResult: NSObject {
// * Websocket-to-REST failover.
@objc(OWSRequestMaker)
public class RequestMaker: NSObject {
public typealias RequestFactoryBlock = (SSKUnidentifiedAccess?) -> TSRequest
public typealias RequestFactoryBlock = (SMKUDAccessKey?) -> TSRequest
public typealias UDAuthFailureBlock = () -> Void
public typealias WebsocketFailureBlock = () -> Void
@ -44,7 +45,7 @@ public class RequestMaker: NSObject {
private let udAuthFailureBlock: UDAuthFailureBlock
private let websocketFailureBlock: WebsocketFailureBlock
private let recipientId: String
private let unidentifiedAccess: SSKUnidentifiedAccess?
private let udAccessKey: SMKUDAccessKey?
private let canFailoverUDAuth: Bool
@objc
@ -52,13 +53,13 @@ public class RequestMaker: NSObject {
udAuthFailureBlock : @escaping UDAuthFailureBlock,
websocketFailureBlock : @escaping WebsocketFailureBlock,
recipientId: String,
unidentifiedAccess: SSKUnidentifiedAccess?,
udAccessKey: SMKUDAccessKey?,
canFailoverUDAuth: Bool) {
self.requestFactoryBlock = requestFactoryBlock
self.udAuthFailureBlock = udAuthFailureBlock
self.websocketFailureBlock = websocketFailureBlock
self.recipientId = recipientId
self.unidentifiedAccess = unidentifiedAccess
self.udAccessKey = udAccessKey
self.canFailoverUDAuth = canFailoverUDAuth
}
@ -99,12 +100,12 @@ public class RequestMaker: NSObject {
}
private func makeRequestInternal(skipUD: Bool, skipWebsocket: Bool) -> Promise<RequestMakerResult> {
var unidentifiedAccessForRequest: SSKUnidentifiedAccess?
var udAccessKeyForRequest: SMKUDAccessKey?
if !skipUD {
unidentifiedAccessForRequest = unidentifiedAccess
udAccessKeyForRequest = udAccessKey
}
let isUDSend = unidentifiedAccessForRequest != nil
let request = requestFactoryBlock(unidentifiedAccessForRequest)
let isUDSend = udAccessKeyForRequest != nil
let request = requestFactoryBlock(udAccessKeyForRequest)
let webSocketType: OWSWebSocketType = (isUDSend ? .UD : .default)
let canMakeWebsocketRequests = (socketManager.canMakeRequests(of: webSocketType) && !skipWebsocket)

@ -34,33 +34,20 @@ public enum UnidentifiedAccessMode: Int {
func setUnidentifiedAccessMode(_ mode: UnidentifiedAccessMode, recipientId: String)
@objc
func getRandomAccess() -> SSKUnidentifiedAccess?
func randomUDAccessKey() -> SMKUDAccessKey
@objc
func getAccess(forRecipientId recipientId: RecipientIdentifier) -> SSKUnidentifiedAccess?
func unidentifiedAccessMode(forRecipientId recipientId: RecipientIdentifier) -> UnidentifiedAccessMode
@objc
func unidentifiedAccessMode(recipientId: RecipientIdentifier) -> UnidentifiedAccessMode
// Returns the UD access key for a given recipient if:
//
// * UD is enabled.
// * Their UD mode is enabled or unrestricted.
// * We have a valid profile key for them.
@objc func enabledUDAccessKeyForRecipient(_ recipientId: RecipientIdentifier) -> SMKUDAccessKey?
// Returns the UD access key for a given recipient if:
//
// * We have a valid profile key for them.
@objc func rawUDAccessKeyForRecipient(_ recipientId: RecipientIdentifier) -> SMKUDAccessKey?
// MARK: - Local State
func udAccessKey(forRecipientId recipientId: RecipientIdentifier) -> SMKUDAccessKey?
// MARK: Sender Certificate
// We use completion handlers instead of a promise so that message sending
// logic can access the strongly typed certificate data.
@objc func ensureSenderCertificateObjC(success:@escaping (SMKSenderCertificate) -> Void,
@objc
func ensureSenderCertificateObjC(success:@escaping (SMKSenderCertificate) -> Void,
failure:@escaping (Error) -> Void)
// MARK: Unrestricted Access
@ -130,36 +117,12 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
// MARK: - Recipient state
@objc
public func getRandomAccess() -> SSKUnidentifiedAccess? {
guard let ourSenderCertificate = senderCertificate() else {
return nil
}
let theirAccessKey = SMKUDAccessKey(randomKeyData: ())
return SSKUnidentifiedAccess(accessKey: theirAccessKey, senderCertificate: ourSenderCertificate)
}
@objc
public func getAccess(forRecipientId recipientId: RecipientIdentifier) -> SSKUnidentifiedAccess? {
let theirAccessMode = unidentifiedAccessMode(recipientId: recipientId)
guard theirAccessMode == .enabled || theirAccessMode == .unrestricted else {
return nil
}
guard let theirAccessKey = enabledUDAccessKeyForRecipient(recipientId) else {
return nil
}
guard let ourSenderCertificate = senderCertificate() else {
return nil
}
return SSKUnidentifiedAccess(accessKey: theirAccessKey, senderCertificate: ourSenderCertificate)
public func randomUDAccessKey() -> SMKUDAccessKey {
return SMKUDAccessKey(randomKeyData: ())
}
@objc
public func unidentifiedAccessMode(recipientId: RecipientIdentifier) -> UnidentifiedAccessMode {
public func unidentifiedAccessMode(forRecipientId recipientId: RecipientIdentifier) -> UnidentifiedAccessMode {
guard let existingRawValue = dbConnection.object(forKey: recipientId, inCollection: kUnidentifiedAccessCollection) as? Int else {
return .unknown
}
@ -183,21 +146,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
// Returns the UD access key for a given recipient
// if we have a valid profile key for them.
@objc
public func enabledUDAccessKeyForRecipient(_ recipientId: RecipientIdentifier) -> SMKUDAccessKey? {
guard isUDEnabled() else {
return nil
}
let theirAccessMode = unidentifiedAccessMode(recipientId: recipientId)
if theirAccessMode == .unrestricted {
return SMKUDAccessKey(randomKeyData: ())
}
return rawUDAccessKeyForRecipient(recipientId)
}
// Returns the UD access key for a given recipient
// if we have a valid profile key for them.
@objc
public func rawUDAccessKeyForRecipient(_ recipientId: RecipientIdentifier) -> SMKUDAccessKey? {
public func udAccessKey(forRecipientId recipientId: RecipientIdentifier) -> SMKUDAccessKey? {
guard let profileKey = profileManager.profileKeyData(forRecipientId: recipientId) else {
// Mark as "not a UD recipient".
return nil
@ -315,7 +264,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
guard let localNumber = tsAccountManager.localNumber() else {
return false
}
let ourAccessMode = unidentifiedAccessMode(recipientId: localNumber)
let ourAccessMode = unidentifiedAccessMode(forRecipientId: localNumber)
return ourAccessMode == .enabled || ourAccessMode == .unrestricted
}

@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ECKeyPair;
@class OWSDevice;
@class PreKeyRecord;
@class SSKUnidentifiedAccess;
@class SMKUDAccessKey;
@class SignedPreKeyRecord;
@class TSRequest;
@ -37,8 +37,8 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)getMessagesRequest;
+ (TSRequest *)getProfileRequestWithRecipientId:(NSString *)recipientId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess
NS_SWIFT_NAME(getProfileRequest(recipientId:unidentifiedAccess:));
udAccessKey:(nullable SMKUDAccessKey *)udAccessKey
NS_SWIFT_NAME(getProfileRequest(recipientId:udAccessKey:));
+ (TSRequest *)turnServerInfoRequest;
@ -62,7 +62,7 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
timeStamp:(uint64_t)timeStamp
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess;
udAccessKey:(nullable SMKUDAccessKey *)udAccessKey;
+ (TSRequest *)verifyCodeRequestWithVerificationCode:(NSString *)verificationCode
forNumber:(NSString *)phoneNumber
@ -78,7 +78,7 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)recipientPrekeyRequestWithRecipient:(NSString *)recipientNumber
deviceId:(NSString *)deviceId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess;
udAccessKey:(nullable SMKUDAccessKey *)udAccessKey;
+ (TSRequest *)registerSignedPrekeyRequestWithSignedPreKeyRecord:(SignedPreKeyRecord *)signedPreKey;

@ -124,14 +124,14 @@ NS_ASSUME_NONNULL_BEGIN
}
+ (TSRequest *)getProfileRequestWithRecipientId:(NSString *)recipientId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess
udAccessKey:(nullable SMKUDAccessKey *)udAccessKey
{
OWSAssertDebug(recipientId.length > 0);
NSString *path = [NSString stringWithFormat:textSecureProfileAPIFormat, recipientId];
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
if (unidentifiedAccess != nil) {
[self useUDAuthWithRequest:request accessKey:unidentifiedAccess.accessKey];
if (udAccessKey != nil) {
[self useUDAuthWithRequest:request accessKey:udAccessKey];
}
return request;
}
@ -188,7 +188,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (TSRequest *)recipientPrekeyRequestWithRecipient:(NSString *)recipientNumber
deviceId:(NSString *)deviceId
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess;
udAccessKey:(nullable SMKUDAccessKey *)udAccessKey
{
OWSAssertDebug(recipientNumber.length > 0);
OWSAssertDebug(deviceId.length > 0);
@ -196,8 +196,8 @@ NS_ASSUME_NONNULL_BEGIN
NSString *path = [NSString stringWithFormat:@"%@/%@/%@", textSecureKeysAPI, recipientNumber, deviceId];
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
if (unidentifiedAccess != nil) {
[self useUDAuthWithRequest:request accessKey:unidentifiedAccess.accessKey];
if (udAccessKey != nil) {
[self useUDAuthWithRequest:request accessKey:udAccessKey];
}
return request;
}
@ -328,7 +328,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId
messages:(NSArray *)messages
timeStamp:(uint64_t)timeStamp
unidentifiedAccess:(nullable SSKUnidentifiedAccess *)unidentifiedAccess
udAccessKey:(nullable SMKUDAccessKey *)udAccessKey
{
// NOTE: messages may be empty; See comments in OWSDeviceManager.
OWSAssertDebug(recipientId.length > 0);
@ -341,8 +341,8 @@ NS_ASSUME_NONNULL_BEGIN
};
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters];
if (unidentifiedAccess != nil) {
[self useUDAuthWithRequest:request accessKey:unidentifiedAccess.accessKey];
if (udAccessKey != nil) {
[self useUDAuthWithRequest:request accessKey:udAccessKey];
}
return request;
}

@ -19,7 +19,6 @@ public protocol SignalServiceClient: SignalServiceClientObjC {
func setCurrentSignedPreKey(_ signedPreKey: SignedPreKeyRecord) -> Promise<Void>
func requestUDSenderCertificate() -> Promise<Data>
func updateAccountAttributes() -> Promise<Void>
func retrieveProfile(recipientId: RecipientIdentifier, unidentifiedAccess: SSKUnidentifiedAccess?) -> Promise<SignalServiceProfile>
}
/// Based on libsignal-service-java's PushServiceSocket class
@ -92,27 +91,4 @@ public class SignalServiceRestClient: NSObject, SignalServiceClient {
let request = OWSRequestFactory.updateAttributesRequest()
return networkManager.makePromise(request: request).asVoid()
}
public func retrieveProfile(recipientId: RecipientIdentifier, unidentifiedAccess: SSKUnidentifiedAccess?) -> Promise<SignalServiceProfile> {
let request = OWSRequestFactory.getProfileRequest(recipientId: recipientId, unidentifiedAccess: unidentifiedAccess)
return networkManager.makePromise(request: request)
.recover { (error: Error) -> Promise<(task: URLSessionDataTask, responseObject: Any?)> in
switch error {
case NetworkManagerError.taskError(let task, _):
let statusCode = task.statusCode()
if unidentifiedAccess != nil && (statusCode == 401 || statusCode == 403) {
Logger.verbose("REST profile request failing over to non-UD auth.")
self.udManager.setUnidentifiedAccessMode(.disabled, recipientId: recipientId)
let nonUDRequest = OWSRequestFactory.getProfileRequest(recipientId: recipientId, unidentifiedAccess: nil)
return self.networkManager.makePromise(request: nonUDRequest)
}
default: break
}
throw error
}.map { _, responseObject in
return try SignalServiceProfile(recipientId: recipientId, responseObject: responseObject)
}
}
}

@ -1,20 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import SignalMetadataKit
@objc
public class SSKUnidentifiedAccess: NSObject {
@objc
let accessKey: SMKUDAccessKey
@objc
let senderCertificate: SMKSenderCertificate
init(accessKey: SMKUDAccessKey, senderCertificate: SMKSenderCertificate) {
self.accessKey = accessKey
self.senderCertificate = senderCertificate
}
}
Loading…
Cancel
Save