Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 107 additions & 25 deletions NextcloudTalk.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

50 changes: 25 additions & 25 deletions NextcloudTalk/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#import "NCNavigationController.h"
#import "NCNotificationController.h"
#import "NCPushNotification.h"
#import "NCPushNotificationsUtils.h"
#import "NCRoomsManager.h"
#import "NCSettingsController.h"
#import "NCUserInterfaceController.h"
Expand Down Expand Up @@ -344,16 +343,19 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N
{
// Called when a background notification is delivered.
NSString *message = [userInfo objectForKey:@"subject"];
NSString *signature = [userInfo objectForKey:@"signature"];

if (!message || !signature) {
return;
}

for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
NSData *pushNotificationPrivateKey = [[NCKeyChainController sharedInstance] pushNotificationPrivateKeyForAccountId:account.accountId];
if (message && pushNotificationPrivateKey) {
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotification:message withDevicePrivateKey:pushNotificationPrivateKey];
if (decryptedMessage) {
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
[[NCNotificationController sharedInstance] processBackgroundPushNotification:pushNotification];

break;
}
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotificationWithMessageBase64:message withSignatureBase64:signature forAccount:account];
if (decryptedMessage) {
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
[[NCNotificationController sharedInstance] processBackgroundPushNotification:pushNotification];

break;
}
}

Expand Down Expand Up @@ -382,25 +384,23 @@ - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayloa
[NCUtils log:@"Received PushKit notification"];

NSString *message = [payload.dictionaryPayload objectForKey:@"subject"];
for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
NSData *pushNotificationPrivateKey = [[NCKeyChainController sharedInstance] pushNotificationPrivateKeyForAccountId:account.accountId];
NSString *signature = [payload.dictionaryPayload objectForKey:@"signature"];

if (!message || !pushNotificationPrivateKey) {
continue;
}

NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotification:message withDevicePrivateKey:pushNotificationPrivateKey];
if (message && signature) {
for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotificationWithMessageBase64:message withSignatureBase64:signature forAccount:account];

if (!decryptedMessage) {
continue;
}
if (!decryptedMessage) {
continue;
}

NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];

if ( pushNotification && pushNotification.type == NCPushNotificationTypeCall) {
[[NCNotificationController sharedInstance] showIncomingCallForPushNotification:pushNotification];
completion();
return;
if (pushNotification && pushNotification.type == NCPushNotificationTypeCall) {
[[NCNotificationController sharedInstance] showIncomingCallForPushNotification:pushNotification];
completion();
return;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion NextcloudTalk/Database/TalkAccount.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
@property NSInteger lastPushSubscription;
@property NSString *deviceIdentifier;
@property NSString *deviceSignature;
@property NSString *userPublicKey;
@property NSString * _Nullable userPublicKey;
@property NSInteger unreadBadgeNumber;
@property BOOL unreadNotification;
@property NSInteger lastContactSync;
Expand Down
16 changes: 16 additions & 0 deletions NextcloudTalk/Notifications/NCPushNotificationKeyPair.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-3.0-or-later
//

@objcMembers
public class NCPushNotificationKeyPair: NSObject {

public var privateKey: Data
public var publicKey: Data

init(privateKey: Data, publicKey: Data) {
self.privateKey = privateKey
self.publicKey = publicKey
}
}
16 changes: 0 additions & 16 deletions NextcloudTalk/Notifications/NCPushNotificationsUtils.h

This file was deleted.

53 changes: 0 additions & 53 deletions NextcloudTalk/Notifications/NCPushNotificationsUtils.m

This file was deleted.

54 changes: 54 additions & 0 deletions NextcloudTalk/Notifications/NCPushNotificationsUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-3.0-or-later
//

import SwiftyRSA

@objcMembers
public class NCPushNotificationsUtils: NSObject {

public static func decryptPushNotification(withMessageBase64 messageBase64: String, withSignatureBase64 signatureBase64: String, forAccount account: TalkAccount) -> String? {
do {
guard let userPublicKeyPem = account.userPublicKey else { return nil }

let encryptedMessage = try EncryptedMessage(base64Encoded: messageBase64)
let userPublicKey = try RsaPublicKey(pemEncoded: userPublicKeyPem)
let signature = try Signature(base64Encoded: signatureBase64)

guard try encryptedMessage.verify(with: userPublicKey, signature: signature, digestType: .sha512) else {
return nil
}

guard let devicePrivateKeyData = NCKeyChainController.sharedInstance().pushNotificationPrivateKey(forAccountId: account.accountId),
let devicePrivateKeyPem = String(data: devicePrivateKeyData, encoding: .utf8) else {
return nil
}

let devicePrivateKey = try RsaPrivateKey(pemEncoded: devicePrivateKeyPem)
let clearMessage = try encryptedMessage.decrypted(with: devicePrivateKey, padding: .PKCS1)

return try clearMessage.string(encoding: .utf8)
} catch {
print("decryptPushNotificationError: \(error)")
}

return nil
}

public static func generatePushNotificationKeyPair() -> NCPushNotificationKeyPair? {
do {
let keyPair = try SwiftyRSA.generateRSAKeyPair(sizeInBits: 2048)

let privateKeyPem = try keyPair.privateKey.pemStringPkcs8()
let publicKeyPem = try keyPair.publicKey.pemStringPkcs8()

return NCPushNotificationKeyPair(privateKey: privateKeyPem.data(using: .utf8)!, publicKey: publicKeyPem.data(using: .utf8)!)
} catch {
NCUtils.log("Error generating push keypair: \(error)")
}

return nil
}

}
59 changes: 17 additions & 42 deletions NextcloudTalk/Security/CCCertificate.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@

#import "CCCertificate.h"

#import <openssl/x509.h>
#import <openssl/bio.h>
#import <openssl/err.h>
#import <openssl/pem.h>

#import "NCAppBranding.h"

#import "NextcloudTalk-Swift.h"

@implementation CCCertificate

NSString *const appCertificates = @"Library/Application Support/Certificates";
Expand Down Expand Up @@ -79,45 +76,23 @@ - (BOOL)checkTrustedChallenge:(NSURLAuthenticationChallenge *)challenge
- (void)saveCertificate:(SecTrustRef)trust withName:(NSString *)certName
{
SecCertificateRef currentServerCert = SecTrustGetLeafCertificate(trust);

CFDataRef data = SecCertificateCopyData(currentServerCert);
X509 *x509cert = NULL;
if (data) {
BIO *mem = BIO_new_mem_buf((void *)CFDataGetBytePtr(data), (int)CFDataGetLength(data));
x509cert = d2i_X509_bio(mem, NULL);
BIO_free(mem);
CFRelease(data);

if (!x509cert) {

NSLog(@"[LOG] OpenSSL couldn't parse X509 Certificate");

} else {

NSString *localCertificatesFolder = [self getDirectoryCerificates];

certName = [NSString stringWithFormat:@"%@/%@",localCertificatesFolder,certName];

if ([[NSFileManager defaultManager] fileExistsAtPath:certName]) {
NSError *error;
[[NSFileManager defaultManager] removeItemAtPath:certName error:&error];
}

FILE *file;
file = fopen([certName UTF8String], "w");
if (file) {
PEM_write_X509(file, x509cert);
}
fclose(file);
}

} else {

NSLog(@"[LOG] Failed to retrieve DER data from Certificate Ref");

if (!data) {
return;
}

//Free
X509_free(x509cert);

NSData *nsData = (__bridge NSData *)(data);
NSString *base64Certificate = [nsData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed];

if (!base64Certificate) {
return;
}

NSString *localCertificatesFolder = [self getDirectoryCerificates];
certName = [NSString stringWithFormat:@"%@/%@", localCertificatesFolder, certName];

[base64Certificate writeToFile:certName atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

- (void)presentViewControllerCertificateWithTitle:(NSString *)title viewController:(UIViewController *)viewController delegate:(id)delegate
Expand Down
4 changes: 2 additions & 2 deletions NextcloudTalk/Settings/NCKeyChainController.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ extern NSString * const kNCPushKitTokenKey;
- (void)setToken:(NSString *)token forAccountId:(NSString *)accountId;
- (NSString *)tokenForAccountId:(NSString *)accountId;
- (void)setPushNotificationPublicKey:(NSData *)privateKey forAccountId:(NSString *)accountId;
- (NSData *)pushNotificationPublicKeyForAccountId:(NSString *)accountId;
- (NSData * _Nullable)pushNotificationPublicKeyForAccountId:(NSString *)accountId;
- (void)setPushNotificationPrivateKey:(NSData *)privateKey forAccountId:(NSString *)accountId;
- (NSData *)pushNotificationPrivateKeyForAccountId:(NSString *)accountId;
- (NSData * _Nullable)pushNotificationPrivateKeyForAccountId:(NSString *)accountId;
- (NSString *)pushTokenSHA512;
- (void)logCombinedPushToken;
- (NSString *)combinedPushToken;
Expand Down
1 change: 0 additions & 1 deletion NextcloudTalk/Settings/NCSettingsController.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ typedef NS_ENUM(NSInteger, NCPreferredFileSorting) {
- (void)connectDisconnectedExternalSignalingControllers;
- (void)disconnectAllExternalSignalingControllers;
- (void)subscribeForPushNotificationsForAccountId:(NSString *)accountId withCompletionBlock:(SubscribeForPushNotificationsCompletionBlock)block;
- (NSInteger)chatMaxLengthConfigCapability;
- (BOOL)canCreateGroupAndPublicRooms;
- (BOOL)isGuestsAppEnabled;
- (BOOL)isReferenceApiSupported;
Expand Down
Loading
Loading