summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2013-06-19 19:05:12 +0200
committerParménides GV <parmegv@sdf.org>2013-06-19 19:05:12 +0200
commitd475ae617d8dc0994a1294be7c8cca338a68fd9e (patch)
treee024cddb5d030ac423f321b8293449afe094e6cb
parentbffd21a326bcb86d814dd3fe2caf5295ea705f2d (diff)
First round of comments.
This resolves the first step from issue #2908. Next step: Put user message strings into an appropiate place.
-rw-r--r--[l---------]README66
-rw-r--r--src/se/leap/leapclient/ConfigHelper.java59
-rw-r--r--src/se/leap/leapclient/ConfigurationWizard.java63
-rw-r--r--src/se/leap/leapclient/Dashboard.java11
-rw-r--r--src/se/leap/leapclient/LeapHttpClient.java17
-rw-r--r--src/se/leap/leapclient/LeapSRPSession.java19
-rw-r--r--src/se/leap/leapclient/LogInDialog.java31
-rw-r--r--src/se/leap/leapclient/NewProviderDialog.java15
-rw-r--r--src/se/leap/leapclient/ProviderAPI.java121
-rw-r--r--src/se/leap/leapclient/ProviderAPIResultReceiver.java12
-rw-r--r--src/se/leap/leapclient/ProviderListContent.java44
11 files changed, 409 insertions, 49 deletions
diff --git a/README b/README
index c3ca0746..7d57a6e3 120000..100644
--- a/README
+++ b/README
@@ -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 0e50c7dd..5838f529 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 6f26adcc..91b92d65 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 c1f4697d..e8ea2705 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 00ee15e9..42f9a523 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 0a8e735f..beb286da 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 c20413d7..00429d10 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 60ac8d2a..5b84ec03 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 f98e4361..f8d730e7 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 a6a8d9d8..e32f6ffd 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 4cf0a5ff..4ae46099 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 {