summaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/Dashboard.java76
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java42
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/LogInDialog.java15
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java147
-rw-r--r--app/src/main/res/menu/client_dashboard.xml12
-rw-r--r--app/src/main/res/values/strings.xml2
6 files changed, 264 insertions, 30 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index 3c17ebb8..6f18b79a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -21,6 +21,7 @@ import org.json.JSONObject;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.ProviderAPIResultReceiver.Receiver;
+import se.leap.bitmaskclient.SignUpDialog;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DialogFragment;
@@ -50,7 +51,7 @@ import android.widget.Toast;
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author parmegv
*/
-public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface,Receiver {
+public class Dashboard extends Activity implements LogInDialog.LogInDialogInterface, SignUpDialog.SignUpDialogInterface, Receiver {
protected static final int CONFIGURE_LEAP = 0;
protected static final int SWITCH_PROVIDER = 1;
@@ -204,6 +205,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
menu.findItem(R.id.login_button).setVisible(true);
menu.findItem(R.id.logout_button).setVisible(false);
}
+ menu.findItem(R.id.signup_button).setVisible(true);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
@@ -243,6 +245,9 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
case R.id.logout_button:
logOut();
return true;
+ case R.id.signup_button:
+ signUpDialog(((ViewGroup)findViewById(android.R.id.content)).getChildAt(0), Bundle.EMPTY);
+ return true;
default:
return super.onOptionsItemSelected(item);
}
@@ -286,6 +291,15 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
EipServiceFragment eipFragment = (EipServiceFragment) getFragmentManager().findFragmentByTag(EipServiceFragment.TAG);
eipFragment.checkEipSwitch(false);
}
+
+ public void cancelLoginOrSignup() {
+ if(mProgressBar == null) mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+ if(mProgressBar != null) {
+ mProgressBar.setVisibility(ProgressBar.GONE);
+ if(eipStatus == null) eipStatus = (TextView) findViewById(R.id.eipStatus);
+ if(eipStatus != null) eipStatus.setText("");
+ }
+ }
/**
* Asks ProviderAPI to log out.
@@ -340,6 +354,58 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
newFragment.show(fragment_transaction, LogInDialog.TAG);
}
+ @Override
+ public void signUp(String username, String password) {
+ mProgressBar = (ProgressBar) findViewById(R.id.eipProgress);
+ eipStatus = (TextView) findViewById(R.id.eipStatus);
+
+ providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
+ providerAPI_result_receiver.setReceiver(this);
+
+ Intent provider_API_command = new Intent(this, ProviderAPI.class);
+
+ Bundle parameters = new Bundle();
+ parameters.putString(SignUpDialog.USERNAME, username);
+ parameters.putString(SignUpDialog.PASSWORD, password);
+
+ JSONObject provider_json;
+ try {
+ provider_json = new JSONObject(preferences.getString(Provider.KEY, ""));
+ parameters.putString(Provider.API_URL, provider_json.getString(Provider.API_URL) + "/" + provider_json.getString(Provider.API_VERSION));
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ provider_API_command.setAction(ProviderAPI.SRP_REGISTER);
+ provider_API_command.putExtra(ProviderAPI.PARAMETERS, parameters);
+ provider_API_command.putExtra(ProviderAPI.RECEIVER_KEY, providerAPI_result_receiver);
+
+ mProgressBar.setVisibility(ProgressBar.VISIBLE);
+ eipStatus.setText(R.string.signingup_message);
+ //mProgressBar.setMax(4);
+ startService(provider_API_command);
+ }
+
+ /**
+ * Shows the sign up dialog.
+ * @param view from which the dialog is created.
+ */
+ public void signUpDialog(View view, Bundle resultData) {
+ FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
+ Fragment previous_sign_up_dialog = getFragmentManager().findFragmentByTag(SignUpDialog.TAG);
+ if (previous_sign_up_dialog != null) {
+ fragment_transaction.remove(previous_sign_up_dialog);
+ }
+ fragment_transaction.addToBackStack(null);
+
+ DialogFragment newFragment = SignUpDialog.newInstance();
+ if(resultData != null && !resultData.isEmpty()) {
+ newFragment.setArguments(resultData);
+ }
+ newFragment.show(fragment_transaction, SignUpDialog.TAG);
+ }
+
/**
* Asks ProviderAPI to download an authenticated OpenVPN certificate.
* @param session_id cookie for the server to allow us to download the certificate.
@@ -364,7 +430,11 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
- if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL){
+ if(resultCode == ProviderAPI.SRP_REGISTRATION_SUCCESSFUL){
+ authenticate(resultData.getString(LogInDialog.USERNAME), resultData.getString(LogInDialog.PASSWORD));
+ } else if(resultCode == ProviderAPI.SRP_REGISTRATION_FAILED){
+ signUpDialog(((ViewGroup)findViewById(android.R.id.content)).getChildAt(0), resultData);
+ } else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_SUCCESSFUL){
String session_id_cookie_key = resultData.getString(ProviderAPI.SESSION_ID_COOKIE_KEY);
String session_id_string = resultData.getString(ProviderAPI.SESSION_ID_KEY);
setResult(RESULT_OK);
@@ -379,7 +449,7 @@ public class Dashboard extends Activity implements LogInDialog.LogInDialogInterf
//Cookie session_id = new BasicClientCookie(session_id_cookie_key, session_id_string);
downloadAuthedUserCertificate(/*session_id*/);
} else if(resultCode == ProviderAPI.SRP_AUTHENTICATION_FAILED) {
- logInDialog(getCurrentFocus(), resultData);
+ logInDialog(getCurrentFocus(), resultData);
} else if(resultCode == ProviderAPI.LOGOUT_SUCCESSFUL) {
authed_eip = false;
getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE).edit().putBoolean(EIP.AUTHED_EIP, authed_eip).commit();
diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
index a317d95e..29b429d1 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java
@@ -16,13 +16,13 @@
*/
package se.leap.bitmaskclient;
+
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
-
import org.jboss.security.srp.SRPParameters;
/**
@@ -42,6 +42,7 @@ public class LeapSRPSession {
final public static String M2 = "M2";
final public static String TOKEN = "token";
final public static String AUTHORIZATION_HEADER= "Authorization";
+ final public static String TAG= "Leap SRP session class tag";
private SRPParameters params;
private String username;
@@ -155,14 +156,23 @@ public class LeapSRPSession {
return x_digest_bytes;
}
+ public byte[] calculateNewSalt() {
+ try {
+ BigInteger salt = new BigInteger(64, SecureRandom.getInstance("SHA1PRNG"));
+ return salt.toByteArray();
+ } catch(NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
/**
* Calculates the parameter V of the SRP-6a algorithm.
- * @param k_string constant k predefined by the SRP server implementation.
* @return the value of V
*/
- private BigInteger calculateV(String k_string) {
- BigInteger k = new BigInteger(k_string, 16);
- BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N
+ public BigInteger calculateV(String username, String password, byte[] salt) {
+ byte[] x_bytes = calculatePasswordHash(username, password, ConfigHelper.trim(salt));
+ x = new BigInteger(1, x_bytes);
+ BigInteger v = g.modPow(x, N); // g^x % N
return v;
}
@@ -209,17 +219,11 @@ public class LeapSRPSession {
* @return the parameter M1
* @throws NoSuchAlgorithmException
*/
- public byte[] response(byte[] salt_bytes, byte[] Bbytes) throws NoSuchAlgorithmException {
+ public byte[] response(byte[] salt_bytes, byte[] Bbytes) {
// Calculate x = H(s | H(U | ':' | password))
byte[] M1 = null;
if(new BigInteger(1, Bbytes).mod(new BigInteger(1, N_bytes)) != BigInteger.ZERO) {
- byte[] xb = calculatePasswordHash(username, password, ConfigHelper.trim(salt_bytes));
- this.x = new BigInteger(1, xb);
-
- // Calculate v = kg^x mod N
- String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0";
- this.v = calculateV(k_string);
-
+ this.v = calculateV(username, password, salt_bytes);
// H(N)
byte[] digest_of_n = newDigest().digest(N_bytes);
@@ -253,8 +257,7 @@ public class LeapSRPSession {
byte[] S_bytes = ConfigHelper.trim(S.toByteArray());
// K = SessionHash(S)
- String hash_algorithm = params.hashAlgorithm;
- MessageDigest sessionDigest = MessageDigest.getInstance(hash_algorithm);
+ MessageDigest sessionDigest = newDigest();
K = ConfigHelper.trim(sessionDigest.digest(S_bytes));
// clientHash = H(N) xor H(g) | H(U) | A | B | K
@@ -283,8 +286,9 @@ public class LeapSRPSession {
BigInteger B = new BigInteger(1, Bbytes);
BigInteger u = new BigInteger(1, u_bytes);
-
- BigInteger B_minus_v = B.subtract(v);
+ String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0";
+ BigInteger k = new BigInteger(k_string, 16);
+ BigInteger B_minus_v = B.subtract(k.multiply(v));
BigInteger a_ux = a.add(u.multiply(x));
BigInteger S = B_minus_v.modPow(a_ux, N);
return S;
@@ -338,4 +342,8 @@ public class LeapSRPSession {
}
return md;
}
+
+ public byte[] getK() {
+ return K;
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
index a28c9049..45d3a373 100644
--- a/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/LogInDialog.java
@@ -99,6 +99,14 @@ public class LogInDialog extends DialogFragment {
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
+ interface_with_Dashboard.cancelLoginOrSignup();
+ }
+ })
+ .setNeutralButton(R.string.signup_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ String username = username_field.getText().toString();
+ String password = password_field.getText().toString();
+ interface_with_Dashboard.signUp(username, password);
}
});
@@ -112,13 +120,10 @@ public class LogInDialog extends DialogFragment {
*
*/
public interface LogInDialogInterface {
- /**
- * Starts authentication process.
- * @param username
- * @param password
- */
public void authenticate(String username, String password);
public void cancelAuthedEipOn();
+ public void signUp(String username, String password);
+ public void cancelLoginOrSignup();
}
LogInDialogInterface interface_with_Dashboard;
diff --git a/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
new file mode 100644
index 00000000..120d4eec
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2013 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+ package se.leap.bitmaskclient;
+
+import se.leap.bitmaskclient.R;
+import android.R.color;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.res.ColorStateList;
+import android.os.Bundle;
+import android.provider.CalendarContract.Colors;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.BounceInterpolator;
+import android.widget.EditText;
+import android.widget.TextView;
+
+/**
+ * Implements the sign up dialog, currently without progress dialog.
+ *
+ * It returns to the previous fragment when finished, and sends username and password to the registration method.
+ *
+ * It also notifies the user if the password is not valid.
+ *
+ * @author parmegv
+ *
+ */
+public class SignUpDialog extends DialogFragment {
+
+ final public static String TAG = "signUpDialog";
+ final public static String VERB = "log in";
+ final public static String USERNAME = "username";
+ final public static String PASSWORD = "password";
+ final public static String USERNAME_MISSING = "username missing";
+ final public static String PASSWORD_INVALID_LENGTH = "password_invalid_length";
+
+ private static boolean is_eip_pending = false;
+
+ public AlertDialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ View log_in_dialog_view = inflater.inflate(R.layout.log_in_dialog, null);
+
+ final TextView user_message = (TextView)log_in_dialog_view.findViewById(R.id.user_message);
+ if(getArguments() != null && getArguments().containsKey(getResources().getString(R.string.user_message))) {
+ user_message.setText(getArguments().getString(getResources().getString(R.string.user_message)));
+ } else {
+ user_message.setVisibility(View.GONE);
+ }
+
+ final EditText username_field = (EditText)log_in_dialog_view.findViewById(R.id.username_entered);
+ if(getArguments() != null && getArguments().containsKey(USERNAME)) {
+ String username = getArguments().getString(USERNAME);
+ username_field.setText(username);
+ }
+ if (getArguments() != null && getArguments().containsKey(USERNAME_MISSING)) {
+ username_field.setError(getResources().getString(R.string.username_ask));
+ }
+
+ final EditText password_field = (EditText)log_in_dialog_view.findViewById(R.id.password_entered);
+ if(!username_field.getText().toString().isEmpty() && password_field.isFocusable()) {
+ password_field.requestFocus();
+ }
+ if (getArguments() != null && getArguments().containsKey(PASSWORD_INVALID_LENGTH)) {
+ password_field.setError(getResources().getString(R.string.error_not_valid_password_user_message));
+ }
+ if(getArguments() != null && getArguments().getBoolean(EipServiceFragment.IS_EIP_PENDING, false)) {
+ is_eip_pending = true;
+ }
+
+
+ builder.setView(log_in_dialog_view)
+ .setPositiveButton(R.string.signup_button, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ String username = username_field.getText().toString();
+ String password = password_field.getText().toString();
+ dialog.dismiss();
+ interface_with_Dashboard.signUp(username, password);
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ interface_with_Dashboard.cancelLoginOrSignup();
+ }
+ });
+
+ return builder.create();
+ }
+
+ /**
+ * Interface used to communicate SignUpDialog with Dashboard.
+ *
+ * @author parmegv
+ *
+ */
+ public interface SignUpDialogInterface {
+ public void signUp(String username, String password);
+ public void cancelAuthedEipOn();
+ public void cancelLoginOrSignup();
+ }
+
+ SignUpDialogInterface interface_with_Dashboard;
+
+ /**
+ * @return a new instance of this DialogFragment.
+ */
+ public static DialogFragment newInstance() {
+ SignUpDialog dialog_fragment = new SignUpDialog();
+ return dialog_fragment;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ interface_with_Dashboard = (SignUpDialogInterface) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement SignUpDialogListener");
+ }
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if(is_eip_pending)
+ interface_with_Dashboard.cancelAuthedEipOn();
+ super.onCancel(dialog);
+ }
+}
diff --git a/app/src/main/res/menu/client_dashboard.xml b/app/src/main/res/menu/client_dashboard.xml
index 676c07c7..663231cd 100644
--- a/app/src/main/res/menu/client_dashboard.xml
+++ b/app/src/main/res/menu/client_dashboard.xml
@@ -6,18 +6,20 @@
<item
android:id="@+id/switch_provider"
android:orderInCategory="501"
- android:title="@string/switch_provider_menu_option"/>
+ android:title="@string/switch_provider_menu_option"/>
+ <item
+ android:id="@+id/signup_button"
+ android:title="@string/signup_button"
+ android:visible="false"/>
<item
android:id="@+id/login_button"
android:showAsAction="ifRoom"
android:title="@string/login_button"
- android:visible="false">
- </item>
+ android:visible="false"/>
<item
android:id="@+id/logout_button"
android:showAsAction="ifRoom"
android:title="@string/logout_button"
- android:visible="false">
- </item>
+ android:visible="false"/>
</menu>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 492c48c7..ac692a69 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -116,6 +116,7 @@
<string name="error_no_such_algorithm_exception_user_message">Update the app</string>
<string name="login_button">Log In</string>
<string name="logout_button">Log Out</string>
+ <string name="signup_button">Sign Up</string>
<string name="setup_error_title">Configuration Error</string>
<string name="setup_error_configure_button">Configure</string>
<string name="setup_error_close_button">Exit</string>
@@ -126,6 +127,7 @@
<string name="configuring_provider">Configuring provider</string>
<string name="incorrectly_downloaded_certificate_message">Your anon cert was not downloaded</string>
<string name="authenticating_message">Logging in</string>
+ <string name="signingup_message">Signing up</string>
<string name="logout_message">Logging out from this session.</string>
<string name="log_out_failed_message">Didn\'t logged out.</string>
<string name="succesful_authentication_message">Authentication succeeded.</string>