Sunday, October 5, 2014

ios proper way to trust self-signed server certificate

For ios https connection, the proper way to trust self signed server certificate is to install the root CA certificate (which signs the server certificate) to device profile using MDM or iPhone configuration tool, in that way, the self-signed root certificate will be used by all ios applications on device, and it is handled transparently to the application logic.

Note, simple accept and trust the self-signed certificate on a https web page from Mobile Safari is not enough, as that will only let Safaria accepts the self-signed certificate, and does not install the certificate into device profile, so the other applications will still not trust this self-signed certificate, and fails to establish the https connection with it.

As another option, if a self signed certificate only needs to be trusted by a single application, and you have the full control of the implementation of this application, that is, the application does not use other third party library to establish https network connection, then you can also include a copy of the root certificate into the application bundle and then call SecCertificateCreateWithData and SecTrustSetAnchorCertificates to trust the self-signed certificate. Note usually you will want to trust both the build-in device root CAs and the self-signed root CA, if so, you should also call SecTrustSetAnchorCertificatesOnly with false parameter, so that both of them will be evaluated by a single call to SecTrustEvaluate.

In addition, if you handle the self-signed certificate by your application, you can get the server certificate and its root certificate information from challenge.protectionSpace.serverTrust object by calling the below code. This information can be used to prompt users to decide whether to trust this self signed certificate or not.

        SecTrustRef trust =  challenge.protectionSpace.serverTrust;
        long certCount = SecTrustGetCertificateCount(trust);
        for (int certIndex = 0; certIndex < certCount; certIndex++) {
            SecCertificateRef   thisCertificate;
            
            thisCertificate = SecTrustGetCertificateAtIndex(trust, certIndex);
            NSString* summary = (__bridge NSString *)(SecCertificateCopySubjectSummary ( thisCertificate ));
            NSLog(@"%@", summary);

            //get DER representation of the certificate data and parse it with openssl library
            CFDataRef certData = SecCertificateCopyData ( thisCertificate );
       //... parse the certificate data with OpenSSL library
       //... prompt user with the certificate information
       CFRelease(cerData);

        }

Thursday, October 2, 2014

Difference between Apple Configurator and iPhone Configuration Utility

Apple Configurator and iPhone configuration Utility provide the similar function, but are used for different purpose.

iPhone Configuration Utility is available for both Windows and Mac OS, it is mainly for developer or advanced ios user, to install or remove app, or configure the device setting. One major usage is installing self-signed server root certificate for https connection. The installed root certificate can be used by both mobile safari and client application when establishing https connection. It can also be used to install client certificate (p12) for mutual authentication, but the installed client certificate can only be used by mobile safari and is not accessible by client application.

Apple Configurator is only available for Mac OS, it provides additional function than iPhone Configuration Utility, but it is more complex to use. It is mainly for small business or organization to manage and monitor multiple devices for multiple users as an alternative to other MDM system, so that users can share the same device but keep their own data when using it. Besides the profile and configuration management, it also provides functions of backup and restore per user account, iOS version update. For developers, if you only need to use it to install a profile to a single device, you can still do from "Prepare->Settings->Profile->Install Profiles..." menu, without putting the device under Supervise control.

Both tools do not provide the function of configure the individual application through NSUserDefault change listener as regular MDM server does.




Sunday, September 28, 2014

Best resource to learn ios swift from Apple

With the release of xcode 6 and ios 8, swift is officially available for developers to create ios application. The following are some best resource from Apple to learn swift for ios programming:

Books:

Video

Friday, September 19, 2014

XCode 6 tips: storyboard zoom, ios 7 simulator, check id boolean type broken


1. In order to zoom xcode storyboard, right click on the storyboard window, and select the zoom percentage on the context menu. The shortcut key is too complex to remember.

2. As ios 7 and ios 7.1 are still used by many devices, so in addition to the ios 8 simulators installed with xcode 6, it is better to go to xcode preference->download menu to download the ios 7 and ios 7.1 simulator  for testing.

3. in ios 7,  the usual way to check whether an object is from boolean type is using
NSNumber * n = [NSNumber numberWithBool:YES]; 
if (strcmp([n objCType], @encode(BOOL)) == 0) {
    NSLog(@"this is a bool");
} 
However the above way has broken in ios 8, the workaround is adding an additional check for the classname as below
 if (value != nil &&  [value isKindOfClass:[NSNumber class]] &&
        ( (strcmp([value objCType], @encode(BOOL)) == 0 ||

           (__bridge CFBooleanRef)value == kCFBooleanTrue || (__bridge CFBooleanRef)value == kCFBooleanFalse) ) ) {
    NSLog(@"this is a bool");
} 

Thursday, September 18, 2014

NSUserDefault in xcode 6 ios simulator not deleted with application

After installing xcode 6, when deleting application from ios simulator, the data saved in NSUserDefault does not deleted with the application.

This is a bug in the xcode 6 simulator. To overcome this issue, either reset the simulator or call the below code in didFinishLaunchingWithOptions method

  NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
   [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
 

Tuesday, September 16, 2014

How to debug cordova javascript deviceready event

Debug cordova deviceready javascript event is not possible without making some change in cordova.js, as you cannot attach the desktop browser to the device uiwebview before the html file is loaded, but once it is loaded, the deviceready event is already fired and it is too late to attach the debugger.

In order to debug deviceready event, you can make a small change to do not call the deviceready event handler, until the debugger is attached. The following steps can be used to do so:

1.  In index.html's body element, add a button to manually fire mydeviceready event after the debugger is attached,    


<br><br><button onclick="document.dispatchEvent(new Event('mydeviceready'));">fire deviceready</button>

2. in Index.js and any other js files that listen on "deviceready" event,  change the event name from deviceready

document.addEventListener('deviceready', function 
to mydeviceready:
document.addEventListener('mydeviceready'

3. launch the app, and after attaching the desktop browser, click the "fire deviceready" button to debug device ready event handle.

It is also helpful to wrap cordova callbackFromNative function within setTimeout, so when debugging the cordova js callback, it will not hang in safari.

Sunday, September 14, 2014

how to copy and paste text from mac to ios and android

iOS simulator:

To copy text from mac to ios simulator, first select the text in mac, and then click "Command+c" to copy it.
Then on ios emulator, first click "Command+v", the string will not show up yet, you then need to select the text field and hold until the paste context menu is shown, select paste menu, the text will be pasted into the text field.



Android emulator:

The easiest way to copy text to android emulator is first selecting the text field in android emulator, and from mac terminal window, type the following command to send the string to the emulator


adb shell input text 'my text string to be copied to android emulator'