Skip to content

Commit ddba843

Browse files
committed
Censorship circumvention in Egypt and UAE
* domain fronting * non-websocket message fetching // FREEBIE
1 parent bcd371b commit ddba843

File tree

7 files changed

+250
-11
lines changed

7 files changed

+250
-11
lines changed

Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ source 'https://github.com/CocoaPods/Specs.git'
44
target 'Signal' do
55
pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git'
66
pod 'AxolotlKit', git: 'https://github.com/WhisperSystems/SignalProtocolKit.git'
7-
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git', branch: 'mkirk/check-for-keychain-errors'
7+
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git', branch: 'mkirk/censorship-circumvention'
88
#pod 'SignalServiceKit', path: '../SignalServiceKit'
99
pod 'OpenSSL'
1010
pod 'PastelogKit', '~> 1.3'

Podfile.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ PODS:
4343
- Reachability (3.2)
4444
- SAMKeychain (1.5.2)
4545
- SCWaveformView (1.0.0)
46-
- SignalServiceKit (0.8.1):
46+
- SignalServiceKit (0.9.0):
4747
- '25519'
4848
- AFNetworking
4949
- AxolotlKit
@@ -121,15 +121,15 @@ DEPENDENCIES:
121121
- OpenSSL
122122
- PastelogKit (~> 1.3)
123123
- SCWaveformView (~> 1.0)
124-
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`, branch `mkirk/check-for-keychain-errors`)
124+
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`, branch `mkirk/censorship-circumvention`)
125125
- SocketRocket (from `https://github.com/facebook/SocketRocket.git`)
126126
- ZXingObjC
127127

128128
EXTERNAL SOURCES:
129129
AxolotlKit:
130130
:git: https://github.com/WhisperSystems/SignalProtocolKit.git
131131
SignalServiceKit:
132-
:branch: mkirk/check-for-keychain-errors
132+
:branch: mkirk/censorship-circumvention
133133
:git: https://github.com/WhisperSystems/SignalServiceKit.git
134134
SocketRocket:
135135
:git: https://github.com/facebook/SocketRocket.git
@@ -139,7 +139,7 @@ CHECKOUT OPTIONS:
139139
:commit: 714f5ebe199ecc999b33c6f97a4bb57e2db90e75
140140
:git: https://github.com/WhisperSystems/SignalProtocolKit.git
141141
SignalServiceKit:
142-
:commit: 5ccbd4ca6dcb97032af3641b6689866e2265510f
142+
:commit: 78515377b14f1055c4a87548a7899650b753ce52
143143
:git: https://github.com/WhisperSystems/SignalServiceKit.git
144144
SocketRocket:
145145
:commit: 41b57bb2fc292a814f758441a05243eb38457027
@@ -162,14 +162,14 @@ SPEC CHECKSUMS:
162162
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
163163
SAMKeychain: 1865333198217411f35327e8da61b43de79b635b
164164
SCWaveformView: 52a96750255d817e300565a80c81fb643e233e07
165-
SignalServiceKit: 60f92ec89fbbf3196bd786b88f065c0214db9ca8
165+
SignalServiceKit: 59a79a51b89b963ba94db30cc99ed5212da0bb9f
166166
SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e
167167
SQLCipher: 4c768761421736a247ed6cf412d9045615d53dff
168168
TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c
169169
UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d
170170
YapDatabase: b1e43555a34a5298e23a045be96817a5ef0da58f
171171
ZXingObjC: bf15b3814f7a105b6d99f47da2333c93a063650a
172172

173-
PODFILE CHECKSUM: 52f34af46d045b2c4c012e12a04d06b69f0dae56
173+
PODFILE CHECKSUM: e09325f010ba0ef1fd0bfa07f665e7be73c43ee0
174174

175175
COCOAPODS: 1.0.1

Signal.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
452D1EE81DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452D1EE71DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift */; };
2626
452E3C8E1D935C77002A45B0 /* OWSConversationSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 452E3C8D1D935C77002A45B0 /* OWSConversationSettingsTableViewController.m */; };
2727
452E3C8F1D935C77002A45B0 /* OWSConversationSettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 452E3C8D1D935C77002A45B0 /* OWSConversationSettingsTableViewController.m */; };
28+
452ECA4D1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452ECA4C1E087E7200E2F016 /* MessageFetcherJob.swift */; };
29+
452ECA4E1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452ECA4C1E087E7200E2F016 /* MessageFetcherJob.swift */; };
2830
4531C9C41DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 4531C9C31DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.m */; };
2931
453D28B71D32BA5F00D523F0 /* OWSDisplayedMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B61D32BA5F00D523F0 /* OWSDisplayedMessage.m */; };
3032
453D28BA1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; };
@@ -566,6 +568,7 @@
566568
452D1EE71DCA90D100A57EC4 /* MesssagesBubblesSizeCalculatorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MesssagesBubblesSizeCalculatorTest.swift; path = Models/MesssagesBubblesSizeCalculatorTest.swift; sourceTree = "<group>"; };
567569
452E3C8C1D935C77002A45B0 /* OWSConversationSettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationSettingsTableViewController.h; sourceTree = "<group>"; };
568570
452E3C8D1D935C77002A45B0 /* OWSConversationSettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = OWSConversationSettingsTableViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
571+
452ECA4C1E087E7200E2F016 /* MessageFetcherJob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MessageFetcherJob.swift; path = Jobs/MessageFetcherJob.swift; sourceTree = "<group>"; };
569572
4531C9C21DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JSQMessagesCollectionViewCell+OWS.h"; sourceTree = "<group>"; };
570573
4531C9C31DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "JSQMessagesCollectionViewCell+OWS.m"; sourceTree = "<group>"; };
571574
453CC0361D08E1A60040EBA3 /* sn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sn; path = translations/sn.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -1295,6 +1298,7 @@
12951298
children = (
12961299
451DE9FC1DC1A28200810E42 /* SyncPushTokensJob.swift */,
12971300
45D231761DC7E8F10034FA89 /* SessionResetJob.swift */,
1301+
452ECA4C1E087E7200E2F016 /* MessageFetcherJob.swift */,
12981302
);
12991303
name = Jobs;
13001304
sourceTree = "<group>";
@@ -2923,6 +2927,7 @@
29232927
45C681C61D305C9E0050903A /* OWSDisplayedMessageCollectionViewCell.m in Sources */,
29242928
E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */,
29252929
E197B60D18BBEC1A00F073E5 /* AudioSocket.m in Sources */,
2930+
452ECA4D1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */,
29262931
A5D0699B1A50E9CB004CB540 /* ShowGroupMembersViewController.m in Sources */,
29272932
45855F371D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */,
29282933
FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */,
@@ -3062,6 +3067,7 @@
30623067
B660F7091C29988E00687D6E /* DesiredBufferDepthController.m in Sources */,
30633068
B660F70A1C29988E00687D6E /* DropoutTracker.m in Sources */,
30643069
B660F70B1C29988E00687D6E /* JitterQueue.m in Sources */,
3070+
452ECA4E1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */,
30653071
B660F70C1C29988E00687D6E /* StretchFactorController.m in Sources */,
30663072
B660F70D1C29988E00687D6E /* AnonymousAudioCallbackHandler.m in Sources */,
30673073
B660F70E1C29988E00687D6E /* RemoteIOAudio.m in Sources */,

Signal/Signal-Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
</dict>
3939
</array>
4040
<key>CFBundleVersion</key>
41-
<string>2.6.9.1</string>
41+
<string>2.6.9.4</string>
4242
<key>ITSAppUsesNonExemptEncryption</key>
4343
<false/>
4444
<key>LOGS_EMAIL</key>
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// Created by Michael Kirk on 12/19/16.
2+
// Copyright © 2016 Open Whisper Systems. All rights reserved.
3+
4+
import Foundation
5+
import PromiseKit
6+
7+
@objc(OWSMessageFetcherJob)
8+
class MessageFetcherJob: NSObject {
9+
10+
let TAG = "[MessageFetcherJob]"
11+
var timer: Timer?
12+
13+
// MARK: injected dependencies
14+
let networkManager: TSNetworkManager
15+
let messagesManager: TSMessagesManager
16+
let messageSender: MessageSender
17+
let signalService: OWSSignalService
18+
19+
// var fallbackTransport = false
20+
// ENABLED FOR DEBUG. DO NOT COMMIT!
21+
var fallbackTransport = true
22+
var runPromises = [Double: Promise<Void>]()
23+
24+
init(messagesManager: TSMessagesManager, messageSender: MessageSender, networkManager: TSNetworkManager, signalService: OWSSignalService) {
25+
self.messagesManager = messagesManager
26+
self.networkManager = networkManager
27+
self.messageSender = messageSender
28+
self.signalService = signalService
29+
}
30+
31+
func runAsync() {
32+
Logger.debug("\(TAG) \(#function)")
33+
guard signalService.isCensored else {
34+
Logger.debug("\(self.TAG) delegating message fetching to SocketManager since we're using normal transport.")
35+
TSSocketManager.becomeActive(fromBackgroundExpectMessage: true)
36+
return
37+
}
38+
39+
Logger.info("\(TAG) using fallback message fetching.")
40+
41+
let promiseId = NSDate().timeIntervalSince1970
42+
Logger.debug("\(self.TAG) starting promise: \(promiseId)")
43+
let runPromise = self.fetchUndeliveredMessages().then { (envelopes: [OWSSignalServiceProtosEnvelope], more: Bool) -> () in
44+
for envelope in envelopes {
45+
Logger.info("\(self.TAG) received envelope.")
46+
self.messagesManager.handleReceivedEnvelope(envelope);
47+
48+
self.acknowledgeDelivery(envelope: envelope)
49+
}
50+
if more {
51+
Logger.info("\(self.TAG) more messages, so recursing.")
52+
// recurse
53+
self.runAsync()
54+
}
55+
}.always {
56+
Logger.debug("\(self.TAG) cleaning up promise: \(promiseId)")
57+
self.runPromises[promiseId] = nil
58+
}
59+
60+
// maintain reference to make sure it's not de-alloced prematurely.
61+
runPromises[promiseId] = runPromise
62+
}
63+
64+
// use in DEBUG or wherever you can't receive push notifications to poll for messages.
65+
// Do not use in production.
66+
func startRunLoop(timeInterval: Double) {
67+
Logger.error("\(TAG) Starting message fetch polling. This should not be used in production.");
68+
timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(runAsync), userInfo: nil, repeats: true)
69+
}
70+
71+
func stopRunLoop() {
72+
timer?.invalidate()
73+
timer = nil
74+
}
75+
76+
func parseMessagesResponse(responseObject: Any?) -> (envelopes: [OWSSignalServiceProtosEnvelope], more: Bool)? {
77+
guard let responseObject = responseObject else {
78+
Logger.error("\(self.TAG) response object was surpringly nil")
79+
return nil
80+
}
81+
82+
guard let responseDict = responseObject as? [String: Any] else {
83+
Logger.error("\(self.TAG) response object was not a dictionary")
84+
return nil
85+
}
86+
87+
guard let messageDicts = responseDict["messages"] as? [[String: Any]] else {
88+
Logger.error("\(self.TAG) messages object was not a list of dictionaries")
89+
return nil
90+
}
91+
92+
let moreMessages = { () -> Bool in
93+
if let responseMore = responseDict["more"] as? Bool {
94+
return responseMore
95+
} else {
96+
Logger.warn("\(self.TAG) more object was not a bool. Assuming no more")
97+
return false
98+
}
99+
}()
100+
101+
let envelopes = messageDicts.map { buildEnvelope(messageDict: $0) }.filter { $0 != nil }.map { $0! }
102+
103+
return (
104+
envelopes: envelopes,
105+
more: moreMessages
106+
)
107+
}
108+
109+
func buildEnvelope(messageDict: [String: Any]) -> OWSSignalServiceProtosEnvelope? {
110+
let builder = OWSSignalServiceProtosEnvelopeBuilder()
111+
112+
guard let typeInt = messageDict["type"] as? Int32 else {
113+
Logger.error("\(TAG) message body didn't have type")
114+
return nil
115+
}
116+
117+
guard let type = OWSSignalServiceProtosEnvelopeType(rawValue:typeInt) else {
118+
Logger.error("\(TAG) message body type was invalid")
119+
return nil
120+
}
121+
builder.setType(type)
122+
123+
if let relay = messageDict["relay"] as? String {
124+
builder.setRelay(relay)
125+
}
126+
127+
guard let timestamp = messageDict["timestamp"] as? UInt64 else {
128+
Logger.error("\(TAG) message body didn't have timestamp")
129+
return nil
130+
}
131+
builder.setTimestamp(timestamp)
132+
133+
guard let source = messageDict["source"] as? String else {
134+
Logger.error("\(TAG) message body didn't have source")
135+
return nil
136+
}
137+
builder.setSource(source)
138+
139+
guard let sourceDevice = messageDict["sourceDevice"] as? UInt32 else {
140+
Logger.error("\(TAG) message body didn't have sourceDevice")
141+
return nil
142+
}
143+
builder.setSourceDevice(sourceDevice)
144+
145+
if let encodedLegacyMessage = messageDict["message"] as? String {
146+
Logger.debug("\(TAG) message body had legacyMessage")
147+
if let legacyMessage = Data(base64Encoded: encodedLegacyMessage) {
148+
builder.setLegacyMessage(legacyMessage)
149+
}
150+
}
151+
152+
if let encodedContent = messageDict["content"] as? String {
153+
Logger.debug("\(TAG) message body had content")
154+
if let content = Data(base64Encoded: encodedContent) {
155+
builder.setContent(content)
156+
}
157+
}
158+
159+
return builder.build()
160+
}
161+
162+
func fetchUndeliveredMessages() -> Promise<(envelopes: [OWSSignalServiceProtosEnvelope], more: Bool)> {
163+
return Promise { fulfill, reject in
164+
let messagesRequest = OWSGetMessagesRequest()
165+
166+
self.networkManager.makeRequest(
167+
messagesRequest,
168+
success: { (task: URLSessionDataTask?, responseObject: Any?) -> () in
169+
guard let (envelopes, more) = self.parseMessagesResponse(responseObject: responseObject) else {
170+
Logger.error("\(self.TAG) response object had unexpected content")
171+
return reject(OWSErrorMakeUnableToProcessServerResponseError())
172+
}
173+
174+
fulfill((envelopes: envelopes, more: more))
175+
},
176+
failure: { (task: URLSessionDataTask?, error: Error?) in
177+
guard let error = error else {
178+
Logger.error("\(self.TAG) error was surpringly nil. sheesh rough day.")
179+
return reject(OWSErrorMakeUnableToProcessServerResponseError())
180+
}
181+
182+
reject(error)
183+
})
184+
}
185+
}
186+
187+
func acknowledgeDelivery(envelope: OWSSignalServiceProtosEnvelope) {
188+
let request = OWSAcknowledgeMessageDeliveryRequest(source: envelope.source, timestamp: envelope.timestamp)
189+
self.networkManager.makeRequest(request,
190+
success: { (task: URLSessionDataTask?, responseObject: Any?) -> () in
191+
Logger.debug("\(self.TAG) acknowledged delivery for message at timestamp: \(envelope.timestamp)")
192+
},
193+
failure: { (task: URLSessionDataTask?, error: Error?) in
194+
Logger.debug("\(self.TAG) acknowledging delivery for message at timestamp: \(envelope.timestamp) failed with error: \(error)")
195+
})
196+
}
197+
}

Signal/src/Signal-Bridging-Header.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,33 @@
33
//
44
#import <Foundation/Foundation.h>
55

6+
#import "Cryptography.h"
67
#import "Environment.h"
8+
#import "NSData+Base64.h"
79
#import "OWSContactAvatarBuilder.h"
810
#import "OWSContactsManager.h"
911
#import "OWSLogger.h"
1012
#import "PhoneNumber.h"
1113
#import "PropertyListPreferences.h"
1214
#import "PushManager.h"
1315
#import "RPAccountManager.h"
16+
#import "TSSocketManager.h"
1417
#import "UIFont+OWS.h"
1518
#import "UIUtil.h"
1619
#import <SignalServiceKit/Contact.h>
1720
#import <SignalServiceKit/NSDate+millisecondTimeStamp.h>
21+
#import <SignalServiceKit/OWSAcknowledgeMessageDeliveryRequest.h>
1822
#import <SignalServiceKit/OWSEndSessionMessage.h>
1923
#import <SignalServiceKit/OWSError.h>
24+
#import <SignalServiceKit/OWSGetMessagesRequest.h>
2025
#import <SignalServiceKit/OWSMessageSender.h>
26+
#import <SignalServiceKit/OWSSignalService.h>
2127
#import <SignalServiceKit/TSAccountManager.h>
2228
#import <SignalServiceKit/TSContactThread.h>
2329
#import <SignalServiceKit/TSErrorMessage.h>
2430
#import <SignalServiceKit/TSInfoMessage.h>
31+
#import <SignalServiceKit/TSMessagesManager.h>
32+
#import <SignalServiceKit/TSNetworkManager.h>
2533
#import <SignalServiceKit/TSStorageManager+IdentityKeyStore.h>
2634
#import <SignalServiceKit/TSStorageManager+SessionStore.h>
2735
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>

0 commit comments

Comments
 (0)