Change license to AGPL
This commit:
- Updates the `LICENSE` file
- Start every file with something like:
// Copyright YEAR_FIRST_PUBLISHED Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
---
First, I removed existing license headers with this Ruby 3.1.2 script:
require 'set'
EXTENSIONS_TO_CHECK = Set['.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift']
same = 0
different = 0
all_files = `git ls-files`.lines.map { |line| line.strip }
all_files.each do |relative_path|
if relative_path == 'Pods'
next
end
unless EXTENSIONS_TO_CHECK.include? File.extname(relative_path)
next
end
path = File.expand_path(relative_path)
contents = File.read(path)
new_contents = contents.sub(/\/\/\n\/\/ Copyright .*\n\/\/\n\n/, '')
if contents == new_contents
same += 1
else
different += 1
end
File.write(path, new_contents)
end
puts "updated #{different} file(s), left #{same} untouched"
I'm sure this script could be improved, but it worked well enough.
Then, I created `Scripts/lint/lint-license-headers` and ran it to auto-
fix a lot of files. This changed the mode of some files, but I think
that's actually desirable. For example,
`SignalServiceKit/src/Util/AppContext.m` previously had a mode of
`0755/-rwxr-xr-x`, and it's now `0644/-rw-r--r--`.
Then I fixed some stragglers and updated the precommit script.
See [a similar change in the Desktop app][0].
[0]: 8bfaf598af
411 lines
19 KiB
Swift
411 lines
19 KiB
Swift
//
|
|
// Copyright 2018 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import XCTest
|
|
import Foundation
|
|
import Curve25519Kit
|
|
import SignalCoreKit
|
|
import LibSignalClient
|
|
@testable import SignalServiceKit
|
|
|
|
class OWSUDManagerTest: SSKBaseTestSwift {
|
|
|
|
private var udManagerImpl: OWSUDManagerImpl {
|
|
return SSKEnvironment.shared.udManager as! OWSUDManagerImpl
|
|
}
|
|
|
|
// MARK: - Setup/Teardown
|
|
|
|
let aliceE164 = "+13213214321"
|
|
let aliceUuid = UUID()
|
|
let trustRoot = IdentityKeyPair.generate()
|
|
lazy var aliceAddress = SignalServiceAddress(uuid: aliceUuid, phoneNumber: aliceE164)
|
|
lazy var defaultSenderCert = buildSenderCertificate(uuidOnly: false)
|
|
lazy var uuidOnlySenderCert = buildSenderCertificate(uuidOnly: true)
|
|
|
|
override func setUp() {
|
|
super.setUp()
|
|
|
|
tsAccountManager.registerForTests(withLocalNumber: aliceE164, uuid: aliceUuid)
|
|
(MockSSKEnvironment.shared as! MockSSKEnvironment).setContactsManagerForMock(FakeContactsManager())
|
|
|
|
// Configure UDManager
|
|
self.write { transaction in
|
|
self.profileManager.setProfileKeyData(OWSAES256Key.generateRandom().keyData,
|
|
for: self.aliceAddress,
|
|
userProfileWriter: .tests,
|
|
transaction: transaction)
|
|
}
|
|
|
|
udManagerImpl.trustRoot = ECPublicKey(trustRoot.publicKey)
|
|
udManagerImpl.setSenderCertificate(uuidOnly: true, certificateData: Data(uuidOnlySenderCert.serialize()))
|
|
udManagerImpl.setSenderCertificate(uuidOnly: false, certificateData: Data(defaultSenderCert.serialize()))
|
|
}
|
|
|
|
// MARK: - Tests
|
|
|
|
func testMode_self() {
|
|
XCTAssert(udManagerImpl.hasSenderCertificates())
|
|
|
|
XCTAssert(tsAccountManager.isRegistered)
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
XCTFail("localAddress was unexpectedly nil")
|
|
return
|
|
}
|
|
XCTAssert(localAddress.isValid)
|
|
|
|
do {
|
|
let udAccess = udManagerImpl.udAccess(forAddress: localAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.enabled, udAccess.udAccessMode)
|
|
XCTAssertFalse(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.unknown, address: aliceAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: localAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unknown, udAccess.udAccessMode)
|
|
XCTAssertFalse(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.disabled, address: aliceAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: localAddress, requireSyncAccess: false)
|
|
XCTAssertNil(udAccess)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: aliceAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: localAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.enabled, udAccess.udAccessMode)
|
|
XCTAssertFalse(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.unrestricted, address: aliceAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: localAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unrestricted, udAccess.udAccessMode)
|
|
XCTAssert(udAccess.isRandomKey)
|
|
}
|
|
}
|
|
|
|
func testMode_noProfileKey() {
|
|
XCTAssert(udManagerImpl.hasSenderCertificates())
|
|
|
|
XCTAssert(tsAccountManager.isRegistered)
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
XCTFail("localAddress was unexpectedly nil")
|
|
return
|
|
}
|
|
XCTAssert(localAddress.isValid)
|
|
|
|
// Ensure UD is enabled by setting our own access level to enabled.
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: localAddress)
|
|
|
|
let bobRecipientAddress = SignalServiceAddress(phoneNumber: "+13213214322")
|
|
XCTAssertFalse(bobRecipientAddress.isLocalAddress)
|
|
self.read { transaction in
|
|
XCTAssertNil(self.profileManager.profileKeyData(for: bobRecipientAddress, transaction: transaction))
|
|
}
|
|
|
|
do {
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unknown, udAccess.udAccessMode)
|
|
XCTAssert(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.unknown, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unknown, udAccess.udAccessMode)
|
|
XCTAssert(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.disabled, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)
|
|
XCTAssertNil(udAccess)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)
|
|
XCTAssertNil(udAccess)
|
|
}
|
|
|
|
do {
|
|
// Bob should work in unrestricted mode, even if he doesn't have a profile key.
|
|
udManagerImpl.setUnidentifiedAccessMode(.unrestricted, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unrestricted, udAccess.udAccessMode)
|
|
XCTAssert(udAccess.isRandomKey)
|
|
}
|
|
}
|
|
|
|
func testMode_withProfileKey() {
|
|
XCTAssert(udManagerImpl.hasSenderCertificates())
|
|
|
|
XCTAssert(tsAccountManager.isRegistered)
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
XCTFail("localAddress was unexpectedly nil")
|
|
return
|
|
}
|
|
XCTAssert(localAddress.isValid)
|
|
|
|
// Ensure UD is enabled by setting our own access level to enabled.
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: localAddress)
|
|
|
|
let bobRecipientAddress = SignalServiceAddress(phoneNumber: "+13213214322")
|
|
XCTAssertFalse(bobRecipientAddress.isLocalAddress)
|
|
self.write { transaction in
|
|
self.profileManager.setProfileKeyData(OWSAES256Key.generateRandom().keyData,
|
|
for: bobRecipientAddress,
|
|
userProfileWriter: .tests,
|
|
transaction: transaction)
|
|
}
|
|
|
|
do {
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unknown, udAccess.udAccessMode)
|
|
XCTAssertFalse(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.unknown, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unknown, udAccess.udAccessMode)
|
|
XCTAssertFalse(udAccess.isRandomKey)
|
|
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.disabled, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)
|
|
XCTAssertNil(udAccess)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.enabled, udAccess.udAccessMode)
|
|
XCTAssertFalse(udAccess.isRandomKey)
|
|
}
|
|
|
|
do {
|
|
udManagerImpl.setUnidentifiedAccessMode(.unrestricted, address: bobRecipientAddress)
|
|
let udAccess = udManagerImpl.udAccess(forAddress: bobRecipientAddress, requireSyncAccess: false)!
|
|
XCTAssertNotNil(udAccess)
|
|
XCTAssertEqual(.unrestricted, udAccess.udAccessMode)
|
|
XCTAssert(udAccess.isRandomKey)
|
|
}
|
|
}
|
|
|
|
func test_senderAccess() {
|
|
XCTAssert(udManagerImpl.hasSenderCertificates())
|
|
|
|
XCTAssert(tsAccountManager.isRegistered)
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
XCTFail("localAddress was unexpectedly nil")
|
|
return
|
|
}
|
|
XCTAssert(localAddress.isValid)
|
|
|
|
// Ensure UD is enabled by setting our own access level to enabled.
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: localAddress)
|
|
|
|
let bobRecipientAddress = SignalServiceAddress(phoneNumber: "+13213214322")
|
|
XCTAssertFalse(bobRecipientAddress.isLocalAddress)
|
|
write { transaction in
|
|
self.profileManager.setProfileKeyData(OWSAES256Key.generateRandom().keyData,
|
|
for: bobRecipientAddress,
|
|
userProfileWriter: .tests,
|
|
transaction: transaction)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(.unknown, sendingAccess.udAccess.udAccessMode)
|
|
XCTAssertFalse(sendingAccess.udAccess.isRandomKey)
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.defaultSenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
|
|
// Turn off phone number sharing.
|
|
write { transaction in
|
|
udManagerImpl.setPhoneNumberSharingMode(.nobody,
|
|
updateStorageService: false,
|
|
transaction: transaction.unwrapGrdbWrite)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(.unknown, sendingAccess.udAccess.udAccessMode)
|
|
XCTAssertFalse(sendingAccess.udAccess.isRandomKey)
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.uuidOnlySenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
|
|
// Contacts-only sharing?
|
|
write { transaction in
|
|
udManagerImpl.setPhoneNumberSharingMode(.contactsOnly,
|
|
updateStorageService: false,
|
|
transaction: transaction.unwrapGrdbWrite)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(.unknown, sendingAccess.udAccess.udAccessMode)
|
|
XCTAssertFalse(sendingAccess.udAccess.isRandomKey)
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.uuidOnlySenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
|
|
// Add Bob to our contacts.
|
|
(contactsManager as! FakeContactsManager).systemContacts.append(bobRecipientAddress)
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(.unknown, sendingAccess.udAccess.udAccessMode)
|
|
XCTAssertFalse(sendingAccess.udAccess.isRandomKey)
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.defaultSenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
}
|
|
|
|
func test_certificateChoiceWithPhoneNumberShared() {
|
|
XCTAssert(udManagerImpl.hasSenderCertificates())
|
|
|
|
XCTAssert(tsAccountManager.isRegistered)
|
|
guard let localAddress = tsAccountManager.localAddress else {
|
|
XCTFail("localAddress was unexpectedly nil")
|
|
return
|
|
}
|
|
XCTAssert(localAddress.isValid)
|
|
|
|
// Ensure UD is enabled by setting our own access level to enabled.
|
|
udManagerImpl.setUnidentifiedAccessMode(.enabled, address: localAddress)
|
|
|
|
let bobRecipientAddress = SignalServiceAddress(uuid: UUID(), phoneNumber: "+13213214322")
|
|
XCTAssertFalse(bobRecipientAddress.isLocalAddress)
|
|
write { transaction in
|
|
self.profileManager.setProfileKeyData(OWSAES256Key.generateRandom().keyData,
|
|
for: bobRecipientAddress,
|
|
userProfileWriter: .tests,
|
|
transaction: transaction)
|
|
identityManager.setShouldSharePhoneNumber(with: bobRecipientAddress, transaction: transaction)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.defaultSenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
|
|
// Turn off phone number sharing.
|
|
write { transaction in
|
|
udManagerImpl.setPhoneNumberSharingMode(.nobody,
|
|
updateStorageService: false,
|
|
transaction: transaction.unwrapGrdbWrite)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.defaultSenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
|
|
// Contacts-only sharing?
|
|
write { transaction in
|
|
udManagerImpl.setPhoneNumberSharingMode(.contactsOnly,
|
|
updateStorageService: false,
|
|
transaction: transaction.unwrapGrdbWrite)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.defaultSenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
|
|
// Make sure it resets on clear.
|
|
write { transaction in
|
|
self.profileManager.setProfileKeyData(OWSAES256Key.generateRandom().keyData,
|
|
for: bobRecipientAddress,
|
|
userProfileWriter: .tests,
|
|
transaction: transaction)
|
|
identityManager.clearShouldSharePhoneNumber(with: bobRecipientAddress, transaction: transaction)
|
|
}
|
|
|
|
firstly {
|
|
udManagerImpl.ensureSenderCertificates(certificateExpirationPolicy: .strict)
|
|
}.done { senderCertificates in
|
|
let sendingAccess = self.udManagerImpl.udSendingAccess(forAddress: bobRecipientAddress,
|
|
requireSyncAccess: false,
|
|
senderCertificates: senderCertificates)!
|
|
XCTAssertEqual(sendingAccess.senderCertificate.serialize(),
|
|
self.uuidOnlySenderCert.serialize())
|
|
}.expect(timeout: 1.0)
|
|
}
|
|
|
|
// MARK: - Util
|
|
|
|
func buildSenderCertificate(uuidOnly: Bool) -> SenderCertificate {
|
|
let serverKeys = IdentityKeyPair.generate()
|
|
let serverCert = try! ServerCertificate(keyId: 1,
|
|
publicKey: serverKeys.publicKey,
|
|
trustRoot: trustRoot.privateKey)
|
|
|
|
var senderAddress = try! SealedSenderAddress(e164: nil, uuidString: aliceUuid.uuidString, deviceId: 1)
|
|
if !uuidOnly {
|
|
senderAddress.e164 = aliceE164
|
|
}
|
|
|
|
let expires = NSDate.ows_millisecondTimeStamp() + kWeekInMs
|
|
let senderKeys = IdentityKeyPair.generate()
|
|
return try! SenderCertificate(sender: senderAddress,
|
|
publicKey: senderKeys.publicKey,
|
|
expiration: expires,
|
|
signerCertificate: serverCert,
|
|
signerKey: serverKeys.privateKey)
|
|
}
|
|
}
|