Skip to content

Commit

Permalink
get images over HTTPS with self-signed certificate
Browse files Browse the repository at this point in the history
Co-Authored-By: andrey <motor4ik@gmail.com>
Signed-off-by: Michele Balistreri <michele@bitgamma.com>
  • Loading branch information
bitgamma and flexsurfer committed Feb 10, 2022
1 parent 9850dd5 commit 52afbf4
Show file tree
Hide file tree
Showing 17 changed files with 437 additions and 270 deletions.
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ dependencies {
implementation 'com.github.status-im:function:0.0.1'
implementation 'com.facebook.fresco:fresco:2.2.0'
implementation 'com.facebook.fresco:animated-gif:2.2.0'
implementation "com.squareup.okhttp3:okhttp-tls:3.12.12"
}

def getLocalNDKDir = { ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
import com.reactnativenavigation.react.NavigationReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.modules.network.OkHttpClientProvider;

import java.util.List;

import im.status.ethereum.keycard.RNStatusKeycardPackage;
import im.status.ethereum.module.StatusPackage;
import im.status.ethereum.pushnotifications.PushNotificationPackage;
import im.status.ethereum.StatusOkHttpClientFactory;

public class MainApplication extends NavigationApplication {

Expand Down Expand Up @@ -56,7 +58,9 @@ public ReactNativeHost getReactNativeHost() {
@Override
public void onCreate() {
super.onCreate();


OkHttpClientProvider.setOkHttpClientFactory(new StatusOkHttpClientFactory());

WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG_WEBVIEW == "1");
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package im.status.ethereum;

import android.util.Log;

import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientProvider;

import okhttp3.OkHttpClient;
import okhttp3.Interceptor;
import okhttp3.tls.HandshakeCertificates;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.RuntimeException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import im.status.ethereum.module.StatusPackage;

class StatusOkHttpClientFactory implements OkHttpClientFactory {
public OkHttpClient createNewNetworkModuleClient() {
String certPem = StatusPackage.getImageTLSCert();
X509Certificate cert;

try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certPem.getBytes()));
} catch(Exception e) {
Log.e("StatusOkHttpClientFactory", "Could not parse certificate");
cert = null;
}

HandshakeCertificates clientCertificates = new HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.addTrustedCertificate(cert)
.build();

return OkHttpClientProvider.createClientBuilder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager())
.build();
}
}
76 changes: 72 additions & 4 deletions ios/StatusIm/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,23 @@

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTHTTPRequestHandler.h>

#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>

#import <SDWebImage/SDWebImageDownloaderConfig.h>
#import <SDWebImage/SDWebImageDownloaderOperation.h>

#import <Security/Security.h>

//TODO: properly import the framework
extern NSString* StatusgoImageServerTLSCert();

@interface StatusDownloaderOperation : SDWebImageDownloaderOperation
+ (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;
@end

/*
#if DEBUG
#import <FlipperKit/FlipperClient.h>
Expand All @@ -45,7 +58,7 @@ static void InitializeFlipper(UIApplication *application) {
#endif
*/

@implementation AppDelegate
@implementation AppDelegate
{
UIView *_blankView;
}
Expand Down Expand Up @@ -84,6 +97,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;

SDWebImageDownloaderConfig.defaultDownloaderConfig.operationClass = [StatusDownloaderOperation class];

return YES;
}

Expand Down Expand Up @@ -124,7 +139,7 @@ - (void)applicationWillResignActive:(UIApplication *)application {
[UIView animateWithDuration:0.5 animations:^{
_blankView.alpha = 1;
}];
}
}
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
Expand Down Expand Up @@ -169,14 +184,67 @@ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UI
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;

NSString *notificationType = userInfo[@"notificationType"]; // check your notification type
if (![notificationType isEqual: @"local-notification"]) { // we silence all notifications which are not local
completionHandler(UNNotificationPresentationOptionNone);
return;
}

completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}

@end

@implementation StatusDownloaderOperation

+ (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
__block NSURLCredential *credential = nil;

NSString *pemCert = StatusgoImageServerTLSCert();
pemCert = [pemCert stringByReplacingOccurrencesOfString:@"-----BEGIN CERTIFICATE-----\n" withString:@""];
pemCert = [pemCert stringByReplacingOccurrencesOfString:@"\n-----END CERTIFICATE-----" withString:@""];
NSData *derCert = [[NSData alloc] initWithBase64EncodedString:pemCert options:NSDataBase64DecodingIgnoreUnknownCharacters];
SecCertificateRef certRef = SecCertificateCreateWithData(NULL, (__bridge_retained CFDataRef) derCert);
CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)&certRef, 1, NULL);
SecTrustSetAnchorCertificates(challenge.protectionSpace.serverTrust, certArrayRef);

SecTrustResultType trustResult;
SecTrustEvaluate(challenge.protectionSpace.serverTrust, &trustResult);

if ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultUnspecified)) {
disposition = NSURLSessionAuthChallengeUseCredential;
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
}

if (completionHandler) {
completionHandler(disposition, credential);
}
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] &&
[challenge.protectionSpace.host isEqualToString:@"localhost"]) {
[StatusDownloaderOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
} else {
[super URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
}
}

@end

@implementation RCTHTTPRequestHandler (SelfSigned)

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] &&
[challenge.protectionSpace.host isEqualToString:@"localhost"]) {
[StatusDownloaderOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
} else {
if (completionHandler) {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
}
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@
import java.util.Collections;
import java.util.List;

import statusgo.Statusgo;

public class StatusPackage implements ReactPackage {

private boolean rootedDevice;

public static String getImageTLSCert() {
return Statusgo.imageServerTLSCert();
}

public StatusPackage(boolean rootedDevice) {
this.rootedDevice = rootedDevice;
}
Expand Down
Loading

0 comments on commit 52afbf4

Please sign in to comment.