With iOS 9, Apple is mandating the use of HTTPS. While this is all good and secure, it forces me to convert all my dev/testing servers to HTTPS. I'm developing for Android and iOS.
Things I've already tried/looked at:
Running iOS 8 - not a long term solution
Self signed servers - requires adding code to both platforms.
Adding root certificate - probably the way to go but expensive in terms of hours spent on this.
I'd like to know how other people are handling this. Ideally, I'd like a solution based on 3 (or not based on 1 and 2), which works well with simulator/emulator and doesn't require jumping through hoops and constant tinkering with root certificate on various devices.
I'll also take a solution for iOS only (e.g. #ifdef) as Android can stay on HTTP.
=====================================================================
Update: 20 Dec
My servers are IP address only. No domain name.
Using plist settings is an option. However, an answer would have to be specific and complete. I would expect to see something like a script that removes plist settings for 'release' builds.
I'm not a security person, but I suspect that leaving whitelisted IP addresses for attackers to use are a bad idea.
You can very easily add domain names for your development servers by using a free DNS provider. I use http://freedns.afraid.org/ and they have some shared domain names where you can add names for IP's you need. I sometimes do this just for internal servers to make it easier to remember where they are!
As for the plist; all you are doing when you whitelist a name like that is telling the phone app that it can talk to that server with HTTP. If you #ifdef DEBUG the ability for your app to talk to those endpoints, then you should have compiled out the ability of the end user to switch to it!
If you are still concerned about it and are looking to have a build step that removes the exemption then PlistBuddy is your friend. You can remove an exemption using the following command line.
/usr/libexec/PlistBuddy -c "Delete :NSAppTransportSecurity:NSExceptionDomains:my.devserver.com" Info.plist
Please put this property in your info.plist if you want to work with HTTP/HTTPS with iOS9.
App Transport Security is enabled by default when using NSURLSession, NSURLConnection in iOS9
You can opt-out of ATS for certain URLs in your Info.plist by using NSExceptionDomains. Within the NSExceptionDomains dictionary you can explicitly define URLs that you need exceptions for with ATS. The exceptions you can use are:
NSIncludesSubdomains
NSExceptionAllowsInsecureHTTPLoads
NSExceptionRequiresForwardSecrecy
NSExceptionMinimumTLSVersion
NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
Each of these keys allows you to granularly disable ATS or particular ATS options on domains where you are unable to support them.
You can refer the answers to this question here,
How do I load an HTTP URL with App Transport Security enabled in iOS 9?
Transport security has blocked a cleartext HTTP
Related
When I try out the example: https://threejs.org/examples/webvr_cubes.html on my Android 7.0 Samsung Galaxy 7 phone using the Chrome browser and the Utopia360 headset, everything works and I can enter VR mode. When I try the exact same thing with exactly the same code, only on my local server, I get "Your browser does not support WebVR. See webvr.info for assistance."
The code is exactly the same and the three.js and WebVR.js files are exactly the same except for where the three.js and WebVR.js files are located in the directory structure (i.e. <script src="js/threejs/three.js" type="text/javascript"></script> instead of <script src="../build/three.js"></script>)
The reason is that the threejs page has an embedded origin token to allow webvr to work without setting the chrome flag enable-webvr, but that only works when the page is served from "threejs.org".
You can see this at the top of the demo pages:
<!-- Origin Trial Token, feature = WebXR Device API (For Chrome M69+), origin = https://threejs.org, expires = 2019-01-07 -->
<meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M69+)" data-expires="2019-01-07" content="ArPzyYNrUDiXsGOh647Ya7MtVUA1nM+WFMnPWu7eoF2nQHOP6mTATIbiv0w+k2kFaPofZG/04ZEQdsACq4IA0wQAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU02OSIsImV4cGlyeSI6MTU0Njg4MzAxOH0=">
So you have two choices:
Enable the webvr flag (chrome://flags#enable-webvr) in your phones browser,
Request an origin token that matches the domain of your website here: https://webvr.rocks/chrome_for_android.
Setting the flag worked for me even when page was served via http.
The issue is that you must "serve your WebVR content via HTTPS", according to the Google WebVR status documentation.
Threejs.org is a site that uses HTTPS, but your localhost is almost certainly not delivering the content via a secure connection. That's why you're seeing that misleading warning that "Your browser does not support WebVR", when in fact, it does.
Unfortunately, the available methods to deliver HTTPS via Apache make it sound like the three options to get an SSL certificate for localhosts won't work on Chrome for Android (or are pricey), so using the WebVR polyfill is the best solution for the time being.
It should work even with an untrusted certificate if you proceed. The important thing is that you should have a certificate, of course we are speaking about a development environment 1. However the crucial part: you must use Chrome Canary for Android, see later.
Get Certificate
The easiest way
Use glitch, which is an online full-stack IDE (yep, with node and sqlite, made by the stackoverflow people) which will provide you a trusted subdomain.
Still easy and locally working way.
Creating certificate and corresponding certificate authority (CA)
you should use minica CA tool:
Install minica (You must install and setup a GO and gotools first)
go get github.com/jsha/minica
Run this simple command, you should use you LAN IP instead of localhost, though.
minica --domains localhost
which creates the following files in your working directory
minica-key.pem The private key of your new CA
minica.pem The root certificate of your CA
localhost/cert.pem The certificate of your website
localhost/key.pem The private key to sign of your website certificate.
If you do not know what are these concepts, I recommend this friendly introduction.
Serve your site with your certificate.
You can use the http-server npm package, which is easy to use and can serve certificates
http-server -a 0.0.0.0 -p 8080 -S -C localhost/cert.pem -K localhost/key.pem
then access your site like https://192.168.1.42 or whatever is your LAN IP address.
Install Chrome Canary to your Android
Google play has it.
Setup Chrome Canary flags
Type chrome://flags in your Chrome Canary's URL bar and enable the following flags: #enable-webvr and #enable-gamepad-extensions called WebVR and Gamepad extensions respectively.
Now your are good to go. 2
Notes:
If you plan to deploy your app in production you should acquire a globally trusted certificate from a CA. Let's Encrypt is free and easy automate and backed by the Linux Foundation, and sponsored by many big players.
WebVR on Android Chrome is still unstable and will be changed, so what I wrote will be deprecated soon.
I have this in my .htaccess to require a password but allow certain whitelisted IP addresses without authentication.
Order deny,allow
Deny from all
AuthType basic
AuthName "Admins Only"
AuthUserFile /etc/apache/.htpasswd
Require valid-user
#replace xxx with IP allowed
Allow from xxx.xxx.xxx.xxx
Satisfy any
Using Apache 2.2.16 on RedHat.
Two things are happening here:
It still asks the whitelisted addresses for password, and
when I visit the site on my Android device, I can see the website behind the auth popup, then when I cancel it, I can still browse the site.
Has anyone else experienced similar symptoms and have suggestions?
Note: When I remove the Deny, Allow, and Satisfy rules, the auth works as expected.
Turns out the Satisfy any directive was being met in a couple other locations. Particularly in my apache httpd.conf file, and an .htaccess in a subfolder of the DocumentRoot.
If you're having similar issues with satisfy any, check any other possible locations where .htaccess may be called from and comment out any Order deny,allow and Allow from all statements. Using something along the lines of these commands helped me find the problems (in linux via ssh):
cd /www/documentroot && find -name .htaccess
Or
grep -rli 'allow from all' .
(the 2nd command will search through files so it will take more time)
Or find it in your apache configuration files. Note that you shouldn't have to change the apache config if AllowOverride all is set for your vhost.
I am sending JSON data from Android & iPhone apps to my web2py application.
I have also written an 'm' page that is accessible from Android & iPhone platforms that also makes the same JSON calls.
I understand how to determine if the request is from Android or iOS using the web2py utility request.user_agent() .
I have observed these signatures in the http_user_agent:
"Bundle%20name/1.400.130508 CFNetwork/609.1.4 Darwin/13.0.0" (iOS app)
"Apache-HttpClient/UNAVAILABLE (java 1.4)" (android app)
Is there some python module or comprehensive regexp available to determine if a call is coming from a phone app or a from a browser?
This is tough, because as some comments point out, app authors can set the user agent string to anything they want. Or don't set it at all, in which case the string will be some default text like Apache-HttpClient/UNAVAILABLE (java 1.4) in your post.
There are many similar questions on the subject, I find this one is especially informative:
Parsing HTTP User-Agent string
And that brings us to a possible remedy for you in the form of the httpagentparser python package:
https://pypi.python.org/pypi/httpagentparser/
I updated my Android phone to 4.0.4 and i noticed that a new file nfcee access.xml appeared in the system folder. The idea of the file as far as i understood is the keep a list of signatures, and allow access to the SE and related intends only to the packages that are signed with one of this signatures. So far in this list is of course the signature of the Google Wallet.
Does anybody know how would be the process in future to enter this list? Do you need to ask for permission directly Google?
If you root your phone, you can modify the file. The file contains the list of signatures and package names that are allowed access to the Secure Element (SE). The signatures is a hex-encoded X.509 certificate. To create one, simply include the tag <debug /> in the file and it will print to logcat the hex-encoded signature of applications that are denied SE access, for easy cut-and-paste into this file.
To create an app that can access the SE, you need to add this permission to the manifest:
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
To actually access the SE, you need to access a hidden API by importing com.android.nfc_extras:
import com.android.nfc_extras.NfcAdapterExtras;
import com.android.nfc_extras.NfcAdapterExtras.CardEmulationRoute;
import com.android.nfc_extras.NfcExecutionEnvironment;
The easiest way to make this possible is to compile your app in the Android source code tree by placing it in packages/apps and building it from there. You need to add the following line to the Android.mk makefile to get access to the SE API:
LOCAL_JAVA_LIBRARIES := com.android.nfc_extras
The functions in com.android.nfc_extras allow enabling and disabling the SE, sending commands to it and receiving responses from it (comparable to IsoDep.transceive()).
This is interesting indeed. If entering your certificate and package name in this file is all that is needed, you shouldn't need to talk to Google, just get whoever is building the ROM (yourself if custom ROM, or a particular carrier) to include it. The bigger problem though is,
who do you need to talk to to get the CardManager keys. If it is the carrier, you can also get them to pre-install your applet, so you might not need the keys at runtime (unless you want to use a secure channel to your applet).
Update: Here's a summary of SE support in Android and some more info on how to use the embedded one. In short, it does work, but you can only query stuff of course. It runs JavaCard and is GP 2.1.1 compatible, uses 3DES keys for the secure channel.
http://nelenkov.blogspot.com/2012/08/accessing-embedded-secure-element-in.html
http://nelenkov.blogspot.com/2012/08/android-secure-element-execution.html
BTW, here's the currently allowed cert on my GN 4.0.4. A package is not specified, so any app signed with it will get access to the SE:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
a8:cd:17:c9:3d:a5:d9:90
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=California, L=Mountain View, O=Google Inc., OU=Android, CN=Google NFC
Validity
Not Before: Mar 24 01:06:53 2011 GMT
Not After : Aug 9 01:06:53 2038 GMT
Subject: C=US, ST=California, L=Mountain View, O=Google Inc., OU=Android, CN=Google NFC
With cavets: If you can get your application on the nfcee_access list you can do the following things:
Enable the UICC (sim card) and enable the embedded secure element (if present)
Open a communication channel to the embedded secure element and exchange data
Receive transaction data from the UICC (sim card) if the UICC wants to send you data (you'll be receiver only).
You can do all this if you root your phone. No need to hack the nfcee_access list to do so, you can just intercept all traffic to the nfc-chip to so so.
What you can't do, even with a rooted phone:
Install applets on the UICC / eSE
Log/Monitor/influence the data-transfer between the embedded secure element/UICC and an external reader, e.g. hack payment systems.
Caveat: You can do almost everthing if, and only if you have the knowledge and the secure access-keys to access the embedded SE. However, if you have these information you wouldn't ask on stack-overflow. :-)
This knowledge is a well kept secret and no one will tell you this secret unless you are a company as big as google, mastercard, visa, american-express and the like.
The answer is simply NO you cannot do anything with the Secure Element. Only SE owner or issuer can allow the access to the SE - i.e. it is Google itself, or might be First Data (http://www.firstdata.com/en_us/products/merchants/mobile-commerce/trusted-service-manager-solution.html), but I think this company is responsible only for the Google Wallet itself, not for the SE management - this might done by SK C&C - I have no idea...
Take it also that way - the precondition for using embedded secure element is that you are offering excellent service and you are Google partner or other phone manufacturer partner (unless you are from Facebook or similar company save your time and do not try that). This is not easy and 99.99% of services cannot be there.
Regarding secure element now you can wait until SWP and SIM cards will become more popular and acceptable solution, since you might be able to get contract with MNO on national level easier or hope in NFC-WI and SD card solution or go with stickers or external accessories like iCarte for iPhone.
I am writing an application to help test android devices' capabilities to connect to wlan's with varying security settings (ex. wpa aes peap). However, I noticed that the published android.net.wifi api does not contain fields to set parameters needed for peap and eap-fast authentication. Does anybody know how to establish a connection to peap programatically?
Below is a link that shows the WifiConfiguration() class possessing unpublished fields (ex. eap, phase2, identity, password). However, eclipse will not let me utilize these fields in my code since they are not officially in the android api.
http://www.netmite.com/android/mydroid/1.6/frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.java
I was having a similar problem. The solution is to use "Reflection".
Here is a link that should be very applicable to you.
How to programmatically create and read WEP/EAP WiFi configurations in Android?