Censorship circumvention with attachments v2
This commit is contained in:
parent
e7daaa834f
commit
76abaef2c6
@ -494,11 +494,7 @@ typedef void (^AttachmentDownloadFailure)(NSError *error);
|
||||
TSAttachmentPointer *attachmentPointer = job.attachmentPointer;
|
||||
|
||||
AFHTTPSessionManager *manager = self.cdnSessionManager;
|
||||
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
|
||||
[manager.requestSerializer setValue:OWSMimeTypeApplicationOctetStream forHTTPHeaderField:@"Content-Type"];
|
||||
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
|
||||
NSString *urlPath = [NSString stringWithFormat:@"attachments/%llu", attachmentPointer.serverId];
|
||||
NSURL *url = [[NSURL alloc] initWithString:urlPath relativeToURL:manager.baseURL];
|
||||
|
||||
@ -527,6 +523,7 @@ typedef void (^AttachmentDownloadFailure)(NSError *error);
|
||||
URLString:url.absoluteString
|
||||
parameters:nil
|
||||
error:&serializationError];
|
||||
[request setValue:OWSMimeTypeApplicationOctetStream forHTTPHeaderField:@"Content-Type"];
|
||||
if (serializationError) {
|
||||
return failureHandler(serializationError);
|
||||
}
|
||||
|
||||
@ -144,6 +144,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:@"v2/attachments/form/upload"] method:@"GET" parameters:@{}];
|
||||
}
|
||||
|
||||
+ (TSRequest *)attachmentRequestWithAttachmentId:(UInt64)attachmentId
|
||||
{
|
||||
OWSAssertDebug(attachmentId > 0);
|
||||
|
||||
NSString *path = [NSString stringWithFormat:@"%@/%llu", textSecureAttachmentsAPI, attachmentId];
|
||||
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
|
||||
}
|
||||
|
||||
+ (TSRequest *)availablePreKeysCountRequest
|
||||
{
|
||||
NSString *path = [NSString stringWithFormat:@"%@", textSecureKeysAPI];
|
||||
@ -207,15 +216,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
+ (TSRequest *)updateAttributesRequest
|
||||
{
|
||||
NSString *path = [textSecureAccountsAPI stringByAppendingString:textSecureAttributesAPI];
|
||||
|
||||
NSString *authKey = self.tsAccountManager.serverAuthToken;
|
||||
OWSAssertDebug(authKey.length > 0);
|
||||
NSString *_Nullable pin = [self.ows2FAManager pinCode];
|
||||
|
||||
NSDictionary<NSString *, id> *accountAttributes = [self accountAttributesWithPin:pin authKey:authKey];
|
||||
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:accountAttributes];
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:textSecureAttributesAPI]
|
||||
method:@"PUT"
|
||||
parameters:accountAttributes];
|
||||
}
|
||||
|
||||
+ (TSRequest *)unregisterAccountRequest
|
||||
@ -426,7 +435,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSAssertDebug(authUsername.length > 0);
|
||||
OWSAssertDebug(authPassword.length > 0);
|
||||
|
||||
NSString *path = [NSString stringWithFormat:@"%@/v1/attestation/%@", contactDiscoveryURL, enclaveId];
|
||||
NSString *path = [NSString stringWithFormat:@"v1/attestation/%@", enclaveId];
|
||||
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path]
|
||||
method:@"PUT"
|
||||
parameters:@{
|
||||
@ -435,6 +444,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}];
|
||||
request.authUsername = authUsername;
|
||||
request.authPassword = authPassword;
|
||||
request.customHost = contactDiscoveryURL;
|
||||
request.customCensorshipCircumventionPrefix = contactDiscoveryCensorshipPrefix;
|
||||
|
||||
// Don't bother with the default cookie store;
|
||||
// these cookies are ephemeral.
|
||||
@ -455,7 +466,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
authPassword:(NSString *)authPassword
|
||||
cookies:(NSArray<NSHTTPCookie *> *)cookies
|
||||
{
|
||||
NSString *path = [NSString stringWithFormat:@"%@/v1/discovery/%@", contactDiscoveryURL, enclaveId];
|
||||
NSString *path = [NSString stringWithFormat:@"v1/discovery/%@", enclaveId];
|
||||
|
||||
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path]
|
||||
method:@"PUT"
|
||||
@ -469,6 +480,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
request.authUsername = authUsername;
|
||||
request.authPassword = authPassword;
|
||||
request.customHost = contactDiscoveryURL;
|
||||
request.customCensorshipCircumventionPrefix = contactDiscoveryCensorshipPrefix;
|
||||
|
||||
// Don't bother with the default cookie store;
|
||||
// these cookies are ephemeral.
|
||||
@ -484,7 +497,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
+ (TSRequest *)remoteAttestationAuthRequest
|
||||
{
|
||||
NSString *path = @"/v1/directory/auth";
|
||||
NSString *path = @"v1/directory/auth";
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
|
||||
}
|
||||
|
||||
@ -506,7 +519,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
parameters = @{ @"reason": limitedReason };
|
||||
}
|
||||
NSString *path = [NSString stringWithFormat:@"/v1/directory/feedback-v3/%@", status];
|
||||
NSString *path = [NSString stringWithFormat:@"v1/directory/feedback-v3/%@", status];
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"PUT" parameters:parameters];
|
||||
}
|
||||
|
||||
@ -514,7 +527,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
+ (TSRequest *)udSenderCertificateRequest
|
||||
{
|
||||
NSString *path = @"/v1/certificate/delivery";
|
||||
NSString *path = @"v1/certificate/delivery";
|
||||
return [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic) BOOL shouldHaveAuthorizationHeaders;
|
||||
@property (atomic, nullable) NSString *authUsername;
|
||||
@property (atomic, nullable) NSString *authPassword;
|
||||
@property (atomic, nullable) NSString *customHost;
|
||||
@property (atomic, nullable) NSString *customCensorshipCircumventionPrefix;
|
||||
|
||||
@property (nonatomic, readonly) NSDictionary<NSString *, id> *parameters;
|
||||
|
||||
|
||||
@ -103,6 +103,35 @@ dispatch_queue_t NetworkManagerQueue()
|
||||
password:request.authPassword];
|
||||
}
|
||||
|
||||
// Most of TSNetwork requests are destined for the Signal Service.
|
||||
// When we are domain fronting, we have to target a different host and add a path prefix.
|
||||
// For common Signal-Service requests the host/path-prefix logic is handled by the
|
||||
// sessionManager.
|
||||
//
|
||||
// However, for CDS requests, we need to:
|
||||
// With CC enabled, use the service fronting Hostname but a custom path-prefix
|
||||
// With CC disabled, use the custom directory host, and no path-prefix
|
||||
NSString *requestURLString;
|
||||
if (self.signalService.isCensorshipCircumventionActive && request.customCensorshipCircumventionPrefix.length > 0) {
|
||||
// All fronted requests go through the same host
|
||||
NSURL *customBaseURL = [self.signalService.domainFrontBaseURL
|
||||
URLByAppendingPathComponent:request.customCensorshipCircumventionPrefix];
|
||||
// Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
|
||||
if (![customBaseURL.absoluteString hasSuffix:@"/"]) {
|
||||
customBaseURL = [customBaseURL URLByAppendingPathComponent:@""];
|
||||
}
|
||||
OWSAssertDebug(customBaseURL);
|
||||
requestURLString = [NSURL URLWithString:request.URL.absoluteString relativeToURL:customBaseURL].absoluteString;
|
||||
} else if (request.customHost) {
|
||||
NSURL *customBaseURL = [NSURL URLWithString:request.customHost];
|
||||
OWSAssertDebug(customBaseURL);
|
||||
requestURLString = [NSURL URLWithString:request.URL.absoluteString relativeToURL:customBaseURL].absoluteString;
|
||||
} else {
|
||||
// requests for the signal-service (with or without censorship circumvention)
|
||||
requestURLString = request.URL.absoluteString;
|
||||
}
|
||||
OWSAssertDebug(requestURLString.length > 0);
|
||||
|
||||
// Honor the request's headers.
|
||||
for (NSString *headerField in request.allHTTPHeaderFields) {
|
||||
NSString *headerValue = request.allHTTPHeaderFields[headerField];
|
||||
@ -110,27 +139,21 @@ dispatch_queue_t NetworkManagerQueue()
|
||||
}
|
||||
|
||||
if ([request.HTTPMethod isEqualToString:@"GET"]) {
|
||||
[self.sessionManager GET:request.URL.absoluteString
|
||||
[self.sessionManager GET:requestURLString
|
||||
parameters:request.parameters
|
||||
progress:nil
|
||||
success:success
|
||||
failure:failure];
|
||||
} else if ([request.HTTPMethod isEqualToString:@"POST"]) {
|
||||
[self.sessionManager POST:request.URL.absoluteString
|
||||
[self.sessionManager POST:requestURLString
|
||||
parameters:request.parameters
|
||||
progress:nil
|
||||
success:success
|
||||
failure:failure];
|
||||
} else if ([request.HTTPMethod isEqualToString:@"PUT"]) {
|
||||
[self.sessionManager PUT:request.URL.absoluteString
|
||||
parameters:request.parameters
|
||||
success:success
|
||||
failure:failure];
|
||||
[self.sessionManager PUT:requestURLString parameters:request.parameters success:success failure:failure];
|
||||
} else if ([request.HTTPMethod isEqualToString:@"DELETE"]) {
|
||||
[self.sessionManager DELETE:request.URL.absoluteString
|
||||
parameters:request.parameters
|
||||
success:success
|
||||
failure:failure];
|
||||
[self.sessionManager DELETE:requestURLString parameters:request.parameters success:success failure:failure];
|
||||
} else {
|
||||
OWSLogError(@"Trying to perform HTTP operation with unknown verb: %@", request.HTTPMethod);
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ extern NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidCha
|
||||
|
||||
@interface OWSSignalService : NSObject
|
||||
|
||||
/// For uploading avatar assets.
|
||||
/// For uploading and downloading avatar assets and attachments
|
||||
@property (nonatomic, readonly) AFHTTPSessionManager *CDNSessionManager;
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
@ -27,6 +27,9 @@ extern NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidCha
|
||||
@property (atomic) BOOL isCensorshipCircumventionManuallyDisabled;
|
||||
@property (atomic, nullable) NSString *manualCensorshipCircumventionCountryCode;
|
||||
|
||||
/// should only be accessed if censorship circumvention is active.
|
||||
@property (nonatomic, readonly) NSURL *domainFrontBaseURL;
|
||||
|
||||
/// For interacting with the Signal Service
|
||||
- (AFHTTPSessionManager *)buildSignalServiceSessionManager;
|
||||
|
||||
|
||||
@ -172,6 +172,13 @@ NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidChange =
|
||||
}
|
||||
}
|
||||
|
||||
- (NSURL *)domainFrontBaseURL
|
||||
{
|
||||
OWSAssertDebug(self.isCensorshipCircumventionActive);
|
||||
OWSCensorshipConfiguration *censorshipConfiguration = [self buildCensorshipConfiguration];
|
||||
return censorshipConfiguration.domainFrontBaseURL;
|
||||
}
|
||||
|
||||
- (AFHTTPSessionManager *)buildSignalServiceSessionManager
|
||||
{
|
||||
if (self.isCensorshipCircumventionActive) {
|
||||
@ -204,9 +211,11 @@ NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidChange =
|
||||
(OWSCensorshipConfiguration *)censorshipConfiguration
|
||||
{
|
||||
NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration;
|
||||
|
||||
NSURL *frontingURL = censorshipConfiguration.domainFrontBaseURL;
|
||||
NSURL *baseURL = [frontingURL URLByAppendingPathComponent:serviceCensorshipPrefix];
|
||||
AFHTTPSessionManager *sessionManager =
|
||||
[[AFHTTPSessionManager alloc] initWithBaseURL:censorshipConfiguration.domainFrontBaseURL
|
||||
sessionConfiguration:sessionConf];
|
||||
[[AFHTTPSessionManager alloc] initWithBaseURL:baseURL sessionConfiguration:sessionConf];
|
||||
|
||||
sessionManager.securityPolicy = censorshipConfiguration.domainFrontSecurityPolicy;
|
||||
|
||||
@ -255,9 +264,10 @@ NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidChange =
|
||||
{
|
||||
NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration;
|
||||
|
||||
NSURL *frontingURL = censorshipConfiguration.domainFrontBaseURL;
|
||||
NSURL *baseURL = [frontingURL URLByAppendingPathComponent:cdnCensorshipPrefix];
|
||||
AFHTTPSessionManager *sessionManager =
|
||||
[[AFHTTPSessionManager alloc] initWithBaseURL:censorshipConfiguration.domainFrontBaseURL
|
||||
sessionConfiguration:sessionConf];
|
||||
[[AFHTTPSessionManager alloc] initWithBaseURL:baseURL sessionConfiguration:sessionConf];
|
||||
|
||||
sessionManager.securityPolicy = censorshipConfiguration.domainFrontSecurityPolicy;
|
||||
|
||||
|
||||
@ -33,6 +33,11 @@ typedef NS_ENUM(NSInteger, TSWhisperMessageType) {
|
||||
#define textSecureCDNReflectorHost @"europe-west1-signal-cdn-reflector.cloudfunctions.net"
|
||||
#define contactDiscoveryURL @"https://api.directory.signal.org"
|
||||
#define kUDTrustRoot @"BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF"
|
||||
|
||||
#define serviceCensorshipPrefix @"service"
|
||||
#define cdnCensorshipPrefix @"cdn"
|
||||
#define contactDiscoveryCensorshipPrefix @"directory"
|
||||
|
||||
#define USING_PRODUCTION_SERVICE
|
||||
|
||||
//#else
|
||||
@ -41,17 +46,21 @@ typedef NS_ENUM(NSInteger, TSWhisperMessageType) {
|
||||
//#define textSecureWebSocketAPI @"wss://textsecure-service-staging.whispersystems.org/v1/websocket/"
|
||||
//#define textSecureServerURL @"https://textsecure-service-staging.whispersystems.org/"
|
||||
//#define textSecureCDNServerURL @"https://cdn-staging.signal.org"
|
||||
//#define textSecureServiceReflectorHost @"meek-signal-service-staging.appspot.com";
|
||||
//#define textSecureCDNReflectorHost @"meek-signal-cdn-staging.appspot.com";
|
||||
//#define textSecureServiceReflectorHost @"europe-west1-signal-cdn-reflector.cloudfunctions.net";
|
||||
//#define textSecureCDNReflectorHost @"europe-west1-signal-cdn-reflector.cloudfunctions.net";
|
||||
//#define contactDiscoveryURL @"https://api-staging.directory.signal.org"
|
||||
//#define kUDTrustRoot @"BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx"
|
||||
//
|
||||
//#define serviceCensorshipPrefix @"service-staging"
|
||||
//#define cdnCensorshipPrefix @"cdn-staging"
|
||||
//#define contactDiscoveryCensorshipPrefix @"directory-staging"
|
||||
|
||||
//#endif
|
||||
|
||||
BOOL IsUsingProductionService(void);
|
||||
|
||||
#define textSecureAccountsAPI @"v1/accounts"
|
||||
#define textSecureAttributesAPI @"/attributes/"
|
||||
#define textSecureAttributesAPI @"v1/accounts/attributes/"
|
||||
|
||||
#define textSecureMessagesAPI @"v1/messages/"
|
||||
#define textSecureKeysAPI @"v2/keys"
|
||||
@ -64,7 +73,7 @@ BOOL IsUsingProductionService(void);
|
||||
#define textSecureProfileAPIFormat @"v1/profile/%@"
|
||||
#define textSecureSetProfileNameAPIFormat @"v1/profile/name/%@"
|
||||
#define textSecureProfileAvatarFormAPI @"v1/profile/form/avatar"
|
||||
#define textSecure2FAAPI @"/v1/accounts/pin"
|
||||
#define textSecure2FAAPI @"v1/accounts/pin"
|
||||
|
||||
#define SignalApplicationGroup @"group.org.whispersystems.signal.group"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user