How to incorporate SSL pinning in React Native using axios for api calls.
I came across TrustKit but my continues efforts to use the same ends up crashing my app. I tried both the ways of adding TrustKit.
Via Info.list
<key>TSKConfiguration</key>
<dict>
<key>TSKSwizzleNetworkDelegates</key>
<true/>
<key>TSKPinnedDomains</key>
<dict>
<key>yourDomain.com</key>
<dict>
<key>TSKPublicKeyHashes</key>
<array>
<string>public key 1</string>
<string>public key 2</string>
</array>
<key>TSKPublicKeyAlgorithms</key>
<array>
<string>TSKAlgorithmRsa2048</string>
</array>
<key>TSKIncludeSubdomains</key>
<true/>
<key>TSKEnforcePinning</key>
<true/>
</dict>
</dict>
</dict>
Via AppDelegate.mm within didFinishLaunchingWithOptions
// Override TrustKit's logger method, useful for local debugging
void (^loggerBlock)(NSString *) = ^void(NSString *message)
{
NSLog(#"TrustKit log: %#", message);
};
[TrustKit setLoggerBlock:loggerBlock];
NSDictionary *trustKitConfig =
#{
// Swizzling because we can't access the NSURLSession instance used in React Native's fetch method
kTSKSwizzleNetworkDelegates: #YES,
kTSKPinnedDomains: #{
#"busdue.com" : #{
kTSKIncludeSubdomains: #YES, // Pin all subdomains
kTSKEnforcePinning: #YES, // Block connections if pinning validation failed
kTSKDisableDefaultReportUri: #YES,
kTSKPublicKeyHashes : #[
#"dz0GbS1i4LnBsJwhRw3iuZmVcgqpn+AlxSBRxUbOz0k=",
#"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", // Fake backup key but we need to provide 2 pins
],
},
}};
[TrustKit initSharedInstanceWithConfiguration:trustKitConfig];
[TrustKit sharedInstance].pinningValidatorCallback = ^(TSKPinningValidatorResult *result, NSString *notedHostname, TKSDomainPinningPolicy *policy) {
if (result.finalTrustDecision == TSKTrustEvaluationFailedNoMatchingPin) {
NSLog(#"TrustKit certificate matching failed");
// Add more logging here. i.e. Sentry, BugSnag etc
}
};
I always end up getting this crash (https://i.stack.imgur.com/673OW.png)
Any suggestions are appreciated.
Related
I recently tried converting an Objective-C project to Swift using Swiftify.
The project has been successfully converted and there are no errors/warning but on running the project the application shows a black screen.
The errors in the console are:
Info.plist configuration "Default Configuration" for UIWindowSceneSessionRoleApplication contained UISceneDelegateClassName key, but could not load class with name "SceneDelegate".
and
There is no scene delegate set. A scene delegate class must be specified to use the main storyboard file.
But as it can be seen from my Project hierarchy there is a SceneDelegate class present.
Also the contents of my Info.plist file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
Also please review the screen recording here.
Also here is the link of the project.
The problem is this pair of lines in the Info.plist:
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
The issue is that you think "SceneDelegate" is the name of the SceneDelegate class, but Objective-C does not think so! You have to write:
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
Try to configure your window scene like this:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.makeKeyAndVisible()
let controller = YoursatrtController() // your start controller class name
window?.rootViewController = controller
}
I'm getting (kCFStreamErrorDomainSSL, -9813) when connecting to a client's server.
The client's server has a self signed certificate that I can not change. The app is using AFNetworking 3.x. I've tried the following but nothing seems to work.
If someone could help me, it will be much appreciated.
Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key> *** CLIENT HOSTNAME *** </key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
AFNetworking connection manager:
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
#ifdef USE_SELF_SIGNED_CERT_RULES
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
manager.securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy.validatesDomainName = YES;
#endif
I had the same problem. I tried your solution but it did not work. Settings allowInvalidCertificates , validatesDomainName and AFSSLPinningModeCertificate did not solved my problem. After going through lots of googling I saw the structure of AFSecurityPolicy this class.
There is a function in this class
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
forDomain:(nullable NSString *)domain;
You have to subclass the AFSecurityPolicy and return YES in its implementation. Then you will be able to connect to your server.
My client server was also self-signed.
Settings properties on AFSecurityPolicy does not solve the problem, I wonder why.
Hi I'm trying to get a number from a text file in my server but i'm getting a null value this is the code... I have reed many similar posts trying to solve the problem but non of them has been useful
NSURL *url = [NSURL URLWithString:#"http://www.trailrunningcamp.cl/version.txt"];
NSError* error = nil;
NSString *content = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
NSLog(#"Content = %#", content );
I have added this code to my plist but still got the same result
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>trailrunningcamp.cl</key>
<dict>
<!--Include to allow subdomains-->
<key>NSIncludesSubdomains</key>
<true/>
<!--Include to allow HTTP requests-->
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<!--Include to specify minimum TLS version-->
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
I'm using Xcode 7.2.1 and OS X El Capitan 10.11.3.... before that code worked fine (a year ago) but with the new Xcode does not work... Is it a missconfiguration or a code error?
I'm trying to add a Finder service and all looks fine until I want the service to do its job.
This is the method in my AppDelegate.m:
-(void)uploadFromPasteboard:(NSPasteboard *)pboard userData:(NSString *)udata error:(NSString **)err
{
NSString *filename = [pboard stringForType:NSURLPboardType];
dbg(#"file: %#", filename);
}
The plist configuration:
<key>NSServices</key>
<array>
<dict>
<key>NSRequiredContext</key>
<dict/>
<key>NSMenuItem</key>
<dict>
<key>default</key>
<string>Upload File</string>
</dict>
<key>NSMessage</key>
<string>uploadFromPasteboard</string>
<key>NSPortName</key>
<string>Finder</string>
<key>NSSendTypes</key>
<array>
<string>NSURLPboardType</string>
</array>
<key>NSReturnTypes</key>
<array/>
</dict>
</array>
All seems fine, the service is displayed in the service menu, but when I click it, nothing happens, no logs or anything else, like its not called at all.
Could someone point me whats wrong cos I'm starting to pull my hair hardly :(
Are you setting your service provider instance? Like this (from: Providing a Service):
EncryptoClass* encryptor = [[EncryptoClass alloc] init];
[NSApp setServicesProvider:encryptor];
Merely having this method in your app delegate class is not enough. In the standard application set-up, having this in your app delegate might be sufficient:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[NSApp setServicesProvider: self];
}
Also you're specifying "Finder" for NSPortName. This is probably not correct. From Services Properties (emphasis mine):
NSPortName is the name of the port on which the application should
listen for service requests. Its value depends on how the service
provider application is registered. In most cases, this is the
application name. This property is ignored for Automator workflows
being used as services.
My reading of the documentation is that the application whose name is in NSPortName is the application that will be used to handle the service request. If the name of your app isn't "Finder" (and it shouldn't be, for obvious reasons) then your app will never be called by the service.
I've recently become interested in writing some system services for OS X but since I have no application to advertise the services under I must resort to writing standalone system services. Apple's documentation on System Services is spartan as it is, but its documentation on standalone services is non-existant.
What I have thus far is an Xcode project built from the bundle package, with the two sources HashifyService.h and HashifyService.m. Here is the test code I have:
- (void) doServiceWork:(NSPasteboard *)pboard
userData:(NSString *)userData
error:(NSString **)error {
NSLog(#"Actually in the service now");
NSString *pboardString;
NSArray *types;
NSLog(#"do test magic service! (pboard: %#, types: %#)", pboard, [pboard types]);
NSString* outputString = #"It Worked";
types = [NSArray arrayWithObject:NSStringPboardType];
[pboard declareTypes:types owner:nil];
[pboard setString:outputString forType:NSStringPboardType];
[outputString release];
return;
}
and this is the NSServices entry in my Info.plist:
<dict>
<key>NSMenuItem</key>
<dict>
<key>Menu item title</key>
<string>HashifyTest</string>
</dict>
<key>NSMessage</key>
<string>doServiceWork</string>
<key>NSPortName</key>
<string>HashifyService</string>
<key>NSReturnTypes</key>
<array>
<string>NSStringPboardType</string>
</array>
<key>NSSendTypes</key>
<array>
<string>NSStringPboardType</string>
</array>
</dict>
I then build the service bundle and place it in ~/Library/Services/ where it is appropriately detected and I am given the option to use the service. Upon activating the service, however, an error occurs and is logged to Console:
..../Hashify.service/Contents/MacOS/Hashify: cannot execute binary file
What am I doing wrong?
You need a main() function. That should register the service using NSRegisterServicesProvider() and enter the run loop. That is in the documentation.