diff options
-rw-r--r--[l---------] | README | 66 | ||||
-rw-r--r-- | src/se/leap/leapclient/ConfigHelper.java | 59 | ||||
-rw-r--r-- | src/se/leap/leapclient/ConfigurationWizard.java | 63 | ||||
-rw-r--r-- | src/se/leap/leapclient/Dashboard.java | 11 | ||||
-rw-r--r-- | src/se/leap/leapclient/LeapHttpClient.java | 17 | ||||
-rw-r--r-- | src/se/leap/leapclient/LeapSRPSession.java | 19 | ||||
-rw-r--r-- | src/se/leap/leapclient/LogInDialog.java | 31 | ||||
-rw-r--r-- | src/se/leap/leapclient/NewProviderDialog.java | 15 | ||||
-rw-r--r-- | src/se/leap/leapclient/ProviderAPI.java | 121 | ||||
-rw-r--r-- | src/se/leap/leapclient/ProviderAPIResultReceiver.java | 12 | ||||
-rw-r--r-- | src/se/leap/leapclient/ProviderListContent.java | 44 |
11 files changed, 409 insertions, 49 deletions
@@ -1 +1,65 @@ -README.txt
\ No newline at end of file +Compiling +========= + +Preconditions +---------------- + +1. Android SDK installed (follow instructions from http://developer.android.com/sdk/index.html) +2. API version 16 or version installed. +2. Ant 1.6 or greater + +Instructions to compile +----------------------- + +1. cd $PROJECT_LOCATION/leap_android +2. ./compile.sh + +Postconditions +-------------- + +1. $PROJECT_LOCATION/leap_android/bin/LEAP Android-debug.apk exists + +Running on the emulator +========================= + +Preconditions +----------------- + +1. Android SDK is installed, and its tools are in the PATH. +2. leap_android has been compiled. +3. An avd exists in ~/.android/avd/ (if you do not have one, follow instructions from http://developer.android.com/tools/devices/managing-avds-cmdline.html) + +Instructions to run on the emulator +----------------------------------- + +1. cd $PROJECT_LOCATION/leap_android +1. Run script: ./run.sh @AVD-NAME . (avd names are the names of the files in ~/.android/avd with extension .avd). + +Postconditions +-------------- + +1. LEAP Android is running. + +Debugging from console +====================== + +Preconditions +----------------- + +1. Android SDK is installed, and its tools are in the PATH. +2. leap_android has been compiled. +3. An avd exists in ~/.android/avd/ (if you do not have one, follow instructions from http://developer.android.com/tools/devices/managing-avds-cmdline.html). +4. jdb is installed (this program is part of OpenJDK 7) + +Instructions to debug from the console +----------------------------------- + +1. cd $PROJECT_LOCATION/leap_android +2. Run script: ./debug.sh @AVD-NAME . (avd names are the names of the files in ~/.android/avd with extension .avd). + +Postconditions +-------------- + +1. LEAP Android is running. +2. LEAP Android does not show the message "Application LEAP for Android (process se.leap.leapclient) is waiting for the debugger to attach". +3. You are in a jdb debuggin session. diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index 0e50c7d..5838f52 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -1,10 +1,8 @@ package se.leap.leapclient; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.math.BigInteger; import java.io.InputStream; @@ -21,8 +19,14 @@ import org.json.JSONObject; import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import android.util.Log; +/** + * Stores constants, and implements auxiliary methods used across all LEAP Android classes. + * + * @author parmegv + * @author MeanderingCode + * + */ public class ConfigHelper { public static SharedPreferences shared_preferences; @@ -100,6 +104,11 @@ public class ConfigHelper { return true; } + /** + * Saves a JSON object into class scope Shared Preferences + * @param shared_preferences_key + * @param content + */ public static void saveSharedPref(String shared_preferences_key, JSONObject content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -109,6 +118,11 @@ public class ConfigHelper { shared_preferences_editor.commit(); } + /** + * Saves a String object into class scope Shared Preferences + * @param shared_preferences_key + * @param content + */ public static void saveSharedPref(String shared_preferences_key, String content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -117,7 +131,12 @@ public class ConfigHelper { content); shared_preferences_editor.commit(); } - + + /** + * Saves a boolean object into class scope Shared Preferences + * @param shared_preferences_key + * @param content + */ public static void saveSharedPref(String shared_preferences_key, boolean content) { SharedPreferences.Editor shared_preferences_editor = shared_preferences @@ -126,6 +145,11 @@ public class ConfigHelper { shared_preferences_editor.commit(); } + /** + * Gets String object from class scope Shared Preferences + * @param shared_preferences_key + * @return the string correspondent to the key parameter + */ public static String getStringFromSharedPref(String shared_preferences_key) { String content = null; if ( checkSharedPrefs() ) { @@ -134,6 +158,11 @@ public class ConfigHelper { return content; } + /** + * Gets JSON object from class scope Shared Preferences + * @param shared_preferences_key + * @return the JSON object correspondent to the key parameter + */ public static JSONObject getJsonFromSharedPref(String shared_preferences_key) throws JSONException { JSONObject content = null; if ( checkSharedPrefs() ) { @@ -156,6 +185,11 @@ public class ConfigHelper { return value; } + /** + * Opens a FileInputStream from the user directory of the external storage directory. + * @param filename + * @return a file input stream + */ public static FileInputStream openFileInputStream(String filename) { FileInputStream input_stream = null; File root = Environment.getExternalStorageDirectory(); @@ -169,11 +203,20 @@ public class ConfigHelper { return input_stream; } + /** + * Sets class scope Shared Preferences + * @param shared_preferences + */ public static void setSharedPreferences( SharedPreferences shared_preferences) { ConfigHelper.shared_preferences = shared_preferences; } + /** + * Adds a new X509 certificate given its input stream and its provider name + * @param provider used to store the certificate in the keystore + * @param inputStream from which X509 certificate must be generated. + */ public static void addTrustedCertificate(String provider, InputStream inputStream) { CertificateFactory cf; try { @@ -190,6 +233,11 @@ public class ConfigHelper { } } + /** + * Adds a new X509 certificate given in its string from and using its provider name + * @param provider used to store the certificate in the keystore + * @param certificate + */ public static void addTrustedCertificate(String provider, String certificate) { String filename_to_save = provider + "_certificate.cer"; CertificateFactory cf; @@ -217,6 +265,9 @@ public class ConfigHelper { } } + /** + * @return class wide keystore + */ public static KeyStore getKeystore() { return keystore_trusted; } diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index 6f26adc..91b92d6 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -2,7 +2,6 @@ package se.leap.leapclient; import java.io.IOException;
import java.util.Iterator;
-import java.util.Scanner;
import org.json.JSONException;
import org.json.JSONObject;
@@ -23,6 +22,14 @@ import android.os.Handler; import android.view.View;
import android.widget.Toast;
+/**
+ * Activity that builds and shows the list of known available providers.
+ *
+ * It also allows the user to enter custom providers with a button.
+ *
+ * @author parmegv
+ *
+ */
public class ConfigurationWizard extends Activity
implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogInterface, Receiver {
@@ -154,6 +161,10 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn }
}
+ /**
+ * Loads providers data from url file contained in the project
+ * @return true if the file was read correctly
+ */
private boolean loadPreseededProviders() {
boolean loaded_preseeded_providers = false;
AssetManager asset_manager = getAssets();
@@ -178,20 +189,26 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn return loaded_preseeded_providers;
}
- private void saveProviderJson(ProviderItem current_provider_item) {
+ /**
+ * Saves provider.json file associated with provider.
+ *
+ * If the provider is custom, the file has already been downloaded so we load it from memory.
+ * If not, the file is updated using the provider's URL.
+ * @param provider
+ */
+ private void saveProviderJson(ProviderItem provider) {
JSONObject provider_json = new JSONObject();
try {
- String provider_contents = "";
- if(!current_provider_item.custom) {
- updateProviderDotJson(current_provider_item.name, current_provider_item.provider_json_url, current_provider_item.danger_on);
+ if(!provider.custom) {
+ updateProviderDotJson(provider.name, provider.provider_json_url, provider.danger_on);
} else {
// FIXME!! We should we be updating our seeded providers list at ConfigurationWizard onStart() ?
// I think yes, but if so, where does this list live? leap.se, as it's the non-profit project for the software?
// If not, we should just be getting names/urls, and fetching the provider.json like in custom entries
- provider_json = current_provider_item.provider_json;
+ provider_json = provider.provider_json;
ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json);
ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON));
- ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, current_provider_item.danger_on);
+ ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, provider.danger_on);
mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services));
downloadJSONFiles(mSelectedProvider);
@@ -202,15 +219,21 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn }
}
- private void downloadJSONFiles(ProviderItem current_provider_item) {
+ /**
+ * Asks ProviderAPI to download provider site's certificate and eip-service.json
+ *
+ * URLs are fetched from the provider parameter
+ * @param provider from which certificate and eip-service.json files are going to be downloaded
+ */
+ private void downloadJSONFiles(ProviderItem provider) {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
Bundle method_and_parameters = new Bundle();
- method_and_parameters.putString(ConfigHelper.PROVIDER_KEY, current_provider_item.name);
- method_and_parameters.putString(ConfigHelper.MAIN_CERT_KEY, current_provider_item.cert_json_url);
- method_and_parameters.putString(ConfigHelper.EIP_SERVICE_KEY, current_provider_item.eip_service_json_url);
- method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, current_provider_item.danger_on);
+ method_and_parameters.putString(ConfigHelper.PROVIDER_KEY, provider.name);
+ method_and_parameters.putString(ConfigHelper.MAIN_CERT_KEY, provider.cert_json_url);
+ method_and_parameters.putString(ConfigHelper.EIP_SERVICE_KEY, provider.eip_service_json_url);
+ method_and_parameters.putBoolean(ConfigHelper.DANGER_ON, provider.danger_on);
provider_API_command.putExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA, method_and_parameters);
provider_API_command.putExtra("receiver", providerAPI_result_receiver);
@@ -218,7 +241,10 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn startService(provider_API_command);
}
- private boolean downloadAnonCert() {
+ /**
+ * Asks ProviderAPI to download an anonymous (anon) VPN certificate.
+ */
+ private void downloadAnonCert() {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
Bundle method_and_parameters = new Bundle();
@@ -229,9 +255,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn provider_API_command.putExtra("receiver", providerAPI_result_receiver);
startService(provider_API_command);
- return true;
}
+ /**
+ * Open the new provider dialog
+ * @param view from which the dialog is showed
+ */
public void addNewProvider(View view) {
FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG);
@@ -258,6 +287,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn startService(provider_API_command);
}
+ /**
+ * Asks ProviderAPI to download a new provider.json file
+ * @param provider_name
+ * @param provider_json_url
+ * @param danger_on tells if HTTPS client should bypass certificate errors
+ */
public void updateProviderDotJson(String provider_name, String provider_json_url, boolean danger_on) {
Intent provider_API_command = new Intent(this, ProviderAPI.class);
diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java index c1f4697..e8ea270 100644 --- a/src/se/leap/leapclient/Dashboard.java +++ b/src/se/leap/leapclient/Dashboard.java @@ -229,6 +229,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(provider_API_command); } + /** + * Asks ProviderAPI to log out. + */ public void logOut() { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); @@ -251,6 +254,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf startService(provider_API_command); } + /** + * Shows the log in dialog. + * @param view from which the dialog is created. + */ public void logInDialog(View view) { FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction(); Fragment previous_log_in_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.LOG_IN_DIALOG); @@ -263,6 +270,10 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf newFragment.show(fragment_transaction, ConfigHelper.LOG_IN_DIALOG); } + /** + * Asks ProviderAPI to download an authenticated OpenVPN certificate. + * @param session_id cookie for the server to allow us to download the certificate. + */ private void downloadAuthedUserCertificate(Cookie session_id) { providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler()); providerAPI_result_receiver.setReceiver(this); diff --git a/src/se/leap/leapclient/LeapHttpClient.java b/src/se/leap/leapclient/LeapHttpClient.java index 00ee15e..42f9a52 100644 --- a/src/se/leap/leapclient/LeapHttpClient.java +++ b/src/se/leap/leapclient/LeapHttpClient.java @@ -11,11 +11,22 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.SingleClientConnManager; import android.content.Context; +/** + * Implements an HTTP client, enabling LEAP Android app to manage its own runtime keystore or bypass default Android security measures. + * + * @author rafa + * + */ public class LeapHttpClient extends DefaultHttpClient { final Context context; private static LeapHttpClient client; + /** + * If the class scope client is null, it creates one and imports, if existing, the main certificate from Shared Preferences. + * @param context + * @return the new client. + */ public static LeapHttpClient getInstance(Context context) { if(client == null) { client = new LeapHttpClient(context); @@ -36,6 +47,12 @@ public class LeapHttpClient extends DefaultHttpClient { return new SingleClientConnManager(getParams(), registry); } + /** + * Uses keystore from ConfigHelper for the SSLSocketFactory. + * + * Sets hostname verifier to allow all hostname verifier. + * @return + */ private SSLSocketFactory newSslSocketFactory() { try { KeyStore trusted = ConfigHelper.getKeystore(); diff --git a/src/se/leap/leapclient/LeapSRPSession.java b/src/se/leap/leapclient/LeapSRPSession.java index 0a8e735..beb286d 100644 --- a/src/se/leap/leapclient/LeapSRPSession.java +++ b/src/se/leap/leapclient/LeapSRPSession.java @@ -9,6 +9,14 @@ import java.util.Arrays; import org.jboss.security.Util; import org.jboss.security.srp.SRPParameters; +/** + * Implements all SRP algorithm logic. + * + * It's derived from JBoss implementation, with adjustments to make it work with LEAP platform. + * + * @author parmegv + * + */ public class LeapSRPSession { private SRPParameters params; @@ -133,7 +141,14 @@ public class LeapSRPSession { return v; } - public byte[] xor(byte[] b1, byte[] b2, int length) + /** + * Calculates the trimmed xor from two BigInteger numbers + * @param b1 the positive source to build first BigInteger + * @param b2 the positive source to build second BigInteger + * @param length + * @return + */ + public byte[] xor(byte[] b1, byte[] b2) { //TODO Check if length matters in the order, when b2 is smaller than b1 or viceversa byte[] xor_digest = new BigInteger(1, b1).xor(new BigInteger(1, b2)).toByteArray(); @@ -185,7 +200,7 @@ public class LeapSRPSession { byte[] digest_of_g = newDigest().digest(params.g); // clientHash = H(N) xor H(g) - byte[] xor_digest = xor(digest_of_n, digest_of_g, digest_of_g.length); + byte[] xor_digest = xor(digest_of_n, digest_of_g); clientHash.update(xor_digest); // clientHash = H(N) xor H(g) | H(U) diff --git a/src/se/leap/leapclient/LogInDialog.java b/src/se/leap/leapclient/LogInDialog.java index c20413d..00429d1 100644 --- a/src/se/leap/leapclient/LogInDialog.java +++ b/src/se/leap/leapclient/LogInDialog.java @@ -11,6 +11,16 @@ import android.view.View; import android.widget.EditText; import android.widget.Toast; +/** + * Implements the log in dialog, currently without progress dialog. + * + * It returns to the previous fragment when finished, and sends username and password to the authenticate method. + * + * It also notifies the user if the password is not valid. + * + * @author parmegv + * + */ public class LogInDialog extends DialogFragment { public AlertDialog onCreateDialog(Bundle savedInstanceState) { @@ -43,16 +53,35 @@ public class LogInDialog extends DialogFragment { return builder.create(); } - boolean wellFormedPassword(String entered_password) { + /** + * Validates a password + * @param entered_password + * @return true if the entered password length is greater or equal to eight (8). + */ + private boolean wellFormedPassword(String entered_password) { return entered_password.length() >= 8; } + /** + * Interface used to communicate LogInDialog with Dashboard. + * + * @author parmegv + * + */ public interface LogInDialogInterface { + /** + * Starts authentication process. + * @param username + * @param password + */ public void authenticate(String username, String password); } LogInDialogInterface interface_with_Dashboard; + /** + * @return a new instance of this DialogFragment. + */ public static DialogFragment newInstance() { LogInDialog dialog_fragment = new LogInDialog(); return dialog_fragment; diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 60ac8d2..5b84ec0 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -13,6 +13,12 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; +/** + * Implements the new custom provider dialog. + * + * @author parmegv + * + */ public class NewProviderDialog extends DialogFragment { public interface NewProviderDialogInterface { @@ -21,6 +27,9 @@ public class NewProviderDialog extends DialogFragment { NewProviderDialogInterface interface_with_ConfigurationWizard; + /** + * @return a new instance of this DialogFragment. + */ public static DialogFragment newInstance() { NewProviderDialog dialog_fragment = new NewProviderDialog(); return dialog_fragment; @@ -37,6 +46,7 @@ public class NewProviderDialog extends DialogFragment { } } + @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = getActivity().getLayoutInflater(); @@ -71,6 +81,11 @@ public class NewProviderDialog extends DialogFragment { return builder.create(); } + /** + * Checks if the entered url is valid or not. + * @param entered_url + * @return true if it's not empty nor contains only the protocol. + */ boolean validURL(String entered_url) { return !entered_url.isEmpty() && entered_url.matches("http[s]?://.+") && !entered_url.replaceFirst("http[s]?://", "").isEmpty(); } diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index f98e436..f8d730e 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -55,6 +55,15 @@ import android.os.ResultReceiver; import android.util.Base64; import android.util.Log; +/** + * Implements HTTP api methods used to manage communications with the provider server. + * + * It's an IntentService because it downloads data fromt he Internet, so it operates in the background. + * + * @author parmegv + * @author MeanderingCode + * + */ public class ProviderAPI extends IntentService { public ProviderAPI() { @@ -113,6 +122,11 @@ public class ProviderAPI extends IntentService { } } + /** + * Downloads the main cert and the eip-service.json files given through the task parameter + * @param task + * @return true if eip-service.json was parsed as a JSON object correctly. + */ private boolean downloadJsonFiles(Bundle task) { String cert_url = task.getString(ConfigHelper.MAIN_CERT_KEY); String eip_service_json_url = task.getString(ConfigHelper.EIP_SERVICE_KEY); @@ -128,6 +142,12 @@ public class ProviderAPI extends IntentService { } } + /** + * Starts the authentication process using SRP protocol. + * + * @param task containing: username, password and api url. + * @return a bundle with a boolean value mapped to a key named ConfigHelper.RESULT_KEY, and which is true if authentication was successful. + */ private Bundle authenticateBySRP(Bundle task) { Bundle session_id_bundle = new Bundle(); @@ -168,11 +188,31 @@ public class ProviderAPI extends IntentService { return session_id_bundle; } + /** + * Sends an HTTP POST request to the authentication server with the SRP Parameter A. + * @param server_url + * @param username + * @param clientA First SRP parameter sent + * @return response from authentication server + * @throws ClientProtocolException + * @throws IOException + * @throws JSONException + */ private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException { HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + "login=" + username + "&&" + "A=" + clientA); return sendToServer(post); } + /** + * Sends an HTTP PUT request to the authentication server with the SRP Parameter M1 (or simply M). + * @param server_url + * @param username + * @param m1 Second SRP parameter sent + * @return response from authentication server + * @throws ClientProtocolException + * @throws IOException + * @throws JSONException + */ private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException { HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, Util.trim(m1)).toString(16)); JSONObject json_response = sendToServer(put); @@ -188,6 +228,14 @@ public class ProviderAPI extends IntentService { return session_idAndM2; } + /** + * Executes an HTTP request expecting a JSON response. + * @param request + * @return response from authentication server + * @throws ClientProtocolException + * @throws IOException + * @throws JSONException + */ private JSONObject sendToServer(HttpUriRequest request) throws ClientProtocolException, IOException, JSONException { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); HttpContext localContext = new BasicHttpContext(); @@ -204,6 +252,11 @@ public class ProviderAPI extends IntentService { return json_response; } + /** + * Downloads a provider.json from a given URL, adding a new provider using the given name. + * @param task containing a boolean meaning if the provider is custom or not, another boolean meaning if the user completely trusts this provider, the provider name and its provider.json url. + * @return a bundle with a boolean value mapped to a key named ConfigHelper.RESULT_KEY, and which is true if the update was successful. + */ private Bundle updateProviderDotJSON(Bundle task) { Bundle result = new Bundle(); boolean custom = task.getBoolean(ConfigHelper.CUSTOM); @@ -230,13 +283,18 @@ public class ProviderAPI extends IntentService { return result; } + /** + * Downloads a custom provider provider.json file + * @param task containing a boolean meaning if the user completely trusts this provider, and the provider main url entered in the new custom provider dialog. + * @return true if provider.json file was successfully parsed as a JSON object. + */ private boolean downloadNewProviderDotJSON(Bundle task) { boolean custom = true; boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON); String provider_main_url = (String) task.get(ConfigHelper.PROVIDER_MAIN_URL); String provider_name = provider_main_url.replaceFirst("http[s]?://", "").replaceFirst("\\/", "_"); - String provider_json_url = guessURL(provider_main_url); + String provider_json_url = guessProviderDotJsonURL(provider_main_url); JSONObject provider_json; try { @@ -245,11 +303,20 @@ public class ProviderAPI extends IntentService { } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); + return false; } return true; } + /** + * Tries to download whatever is pointed by the string_url. + * + * If danger_on flag is true, SSL exceptions will be managed by futher methods that will try to use some bypass methods. + * @param string_url + * @param danger_on if the user completely trusts this provider + * @return + */ private String getStringFromProvider(String string_url, boolean danger_on) { String json_file_content = ""; @@ -281,8 +348,15 @@ public class ProviderAPI extends IntentService { return json_file_content; } + /** + * Tries to download a string from given url without verifying the hostname. + * + * If a IOException still occurs, it tries with another bypass method: getStringFromProviderWithCACertAdded. + * @param string_url + * @return an empty string if everything fails, the url content if not. + */ private String getStringFromProviderWithoutValidate( - URL provider_json_url) { + URL string_url) { String json_string = ""; HostnameVerifier hostnameVerifier = new HostnameVerifier() { @@ -294,20 +368,25 @@ public class ProviderAPI extends IntentService { try { HttpsURLConnection urlConnection = - (HttpsURLConnection)provider_json_url.openConnection(); + (HttpsURLConnection)string_url.openConnection(); urlConnection.setHostnameVerifier(hostnameVerifier); json_string = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { - json_string = getStringFromProviderWithCACertAdded(provider_json_url); + json_string = getStringFromProviderWithCACertAdded(string_url); //e.printStackTrace(); } return json_string; } + /** + * Tries to download the contents of the provided url using main certificate from choosen provider. + * @param url + * @return an empty string if it fails, the url content if not. + */ private String getStringFromProviderWithCACertAdded(URL url) { String json_file_content = ""; @@ -372,6 +451,11 @@ public class ProviderAPI extends IntentService { return json_file_content; } + /** + * Downloads the certificate from the parameter url bypassing self signed certificate SSL errors. + * @param certificate_url_string + * @return the certificate, as a string + */ private String downloadCertificateWithoutTrusting(String certificate_url_string) { String cert_string = ""; @@ -424,15 +508,34 @@ public class ProviderAPI extends IntentService { return cert_string; } + /** + * Downloads a JSON object from the given url. + * + * It first downloads the JSON object as a String, and then parses it to JSON object. + * @param json_url + * @param danger_on if the user completely trusts the certificate of the url address. + * @return + * @throws JSONException + */ private JSONObject getJSONFromProvider(String json_url, boolean danger_on) throws JSONException { String json_file_content = getStringFromProvider(json_url, danger_on); return new JSONObject(json_file_content); } - private String guessURL(String provider_main_url) { + /** + * Tries to guess the provider.json url given the main provider url. + * @param provider_main_url + * @return the guessed provider.json url + */ + private String guessProviderDotJsonURL(String provider_main_url) { return provider_main_url + "/provider.json"; } + /** + * Logs out from the api url retrieved from the task. + * @param task containing api url from which the user will log out + * @return true if there were no exceptions + */ private boolean logOut(Bundle task) { DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); int session_id_index = 0; @@ -459,6 +562,12 @@ public class ProviderAPI extends IntentService { return true; } + /** + * Downloads a new OpenVPN certificate, attaching authenticated cookie for authenticated certificate. + * + * @param task containing the type of the certificate to be downloaded + * @return true if certificate was downloaded correctly, false if provider.json or danger_on flag are not present in SharedPreferences, or if the certificate url could not be parsed as a URI, or if there was an SSL error. + */ private boolean getNewCert(Bundle task) { String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE); try { @@ -493,7 +602,7 @@ public class ProviderAPI extends IntentService { } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); + return false; } - return true; } } diff --git a/src/se/leap/leapclient/ProviderAPIResultReceiver.java b/src/se/leap/leapclient/ProviderAPIResultReceiver.java index a6a8d9d..e32f6ff 100644 --- a/src/se/leap/leapclient/ProviderAPIResultReceiver.java +++ b/src/se/leap/leapclient/ProviderAPIResultReceiver.java @@ -4,6 +4,11 @@ import android.os.Bundle; import android.os.Handler;
import android.os.ResultReceiver;
+/**
+ * Implements the ResultReceiver needed by Activities using ProviderAPI to receive the results of its operations.
+ * @author parmegv
+ *
+ */
public class ProviderAPIResultReceiver extends ResultReceiver {
private Receiver mReceiver;
@@ -11,11 +16,16 @@ public class ProviderAPIResultReceiver extends ResultReceiver { super(handler);
// TODO Auto-generated constructor stub
}
-
+
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
+ /**
+ * Interface to enable ProviderAPIResultReceiver to receive results from the ProviderAPI IntentService.
+ * @author parmegv
+ *
+ */
public interface Receiver {
public void onReceiveResult(int resultCode, Bundle resultData);
}
diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index 4cf0a5f..4ae4609 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -10,30 +10,29 @@ import java.util.Map; import org.json.JSONException;
import org.json.JSONObject;
-
+/**
+ * Models the provider list shown in the ConfigurationWizard.
+ *
+ * @author parmegv
+ *
+ */
public class ProviderListContent {
- /**
- * An array of sample (dummy) items.
- */
public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
- /**
- * A map of sample (dummy) items, by ID.
- */
public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
-
- static {
- //addItem(new ProviderItem("1", "bitmask", "https://bitmask.net/provider.json", "https://api.bitmask.net:4430/1/config/eip-service.json"));
- }
+ /**
+ * Adds a new provider item to the end of the items map, and to the items list.
+ * @param item
+ */
public static void addItem(ProviderItem item) {
ITEMS.add(item);
ITEM_MAP.put(String.valueOf(ITEMS.size()), item);
}
/**
- * A dummy item representing a piece of content.
+ * A provider item.
*/
public static class ProviderItem {
public boolean custom = false;
@@ -45,15 +44,13 @@ public class ProviderListContent { public String eip_service_json_url;
public String cert_json_url;
public boolean danger_on = false;
-
- public ProviderItem(String id, String name, String provider_json_url, String eip_service_json_url, String cert_json_url) {
- this.id = id;
- this.name = name;
- this.provider_json_url = provider_json_url;
- this.eip_service_json_url = eip_service_json_url;
- this.cert_json_url = cert_json_url;
- }
+ /**
+ * @param name of the provider
+ * @param urls_file_input_stream file input stream linking with the assets url file
+ * @param custom if it's a new provider entered by the user or not
+ * @param danger_on if the user trusts completely the new provider
+ */
public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) {
try {
@@ -78,6 +75,13 @@ public class ProviderListContent { }
}
+ /**
+ * @param name of the provider
+ * @param provider_json_url used to download provider.json file of the provider
+ * @param provider_json already downloaded
+ * @param custom if it's a new provider entered by the user or not
+ * @param danger_on if the user trusts completely the new provider
+ */
public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) {
try {
|