From 230ae10fb3a0c08cbd16e91fce041133bdf5ae8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 5 May 2014 16:06:53 +0200 Subject: New menu option: signup. There is some problem in the maths, because the server says it's ok but login doesn't work from Android app nor from webapp. --- .../java/se/leap/bitmaskclient/ProviderAPI.java | 9 +- .../main/java/se/leap/bitmaskclient/Dashboard.java | 59 +++++++- .../java/se/leap/bitmaskclient/LeapSRPSession.java | 9 +- .../java/se/leap/bitmaskclient/SignUpDialog.java | 150 +++++++++++++++++++++ app/src/main/res/menu/client_dashboard.xml | 13 +- app/src/main/res/values/strings.xml | 1 + 6 files changed, 228 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java (limited to 'app') diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index f8895983..8678cc80 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -214,27 +214,32 @@ public class ProviderAPI extends IntentService { LeapSRPSession client = new LeapSRPSession(username, password, params); byte[] salted_password = client.calculateSaltedPassword(); /* Calculate password verifier */ - BigInteger password_verifier = client.calculateV(); + BigInteger password_verifier = client.calculateV(username, password, salted_password); /* Send to the server */ try { - sendNewUserDataToSRPServer(authentication_server, username, new BigInteger(salted_password).toString(), password_verifier.toString()); + JSONObject result = sendNewUserDataToSRPServer(authentication_server, username, new BigInteger(salted_password).toString(16), password_verifier.toString()); + Log.d(TAG, result.toString()); broadcast_progress(progress++); } catch (ClientProtocolException e) { // session_id_bundle.putBoolean(RESULT_KEY, false); // session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_client_http_user_message)); // session_id_bundle.putString(LogInDialog.USERNAME, username); + e.printStackTrace(); } catch (IOException e) { // session_id_bundle.putBoolean(RESULT_KEY, false); // session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_io_exception_user_message)); // session_id_bundle.putString(LogInDialog.USERNAME, username); + e.printStackTrace(); } catch (JSONException e) { // session_id_bundle.putBoolean(RESULT_KEY, false); // session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_json_exception_user_message)); // session_id_bundle.putString(LogInDialog.USERNAME, username); + e.printStackTrace(); } catch (NoSuchAlgorithmException e) { // session_id_bundle.putBoolean(RESULT_KEY, false); // session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_no_such_algorithm_exception_user_message)); // session_id_bundle.putString(LogInDialog.USERNAME, username); + e.printStackTrace(); } catch (KeyManagementException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java index 3c17ebb8..241286bb 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 * @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); } @@ -340,6 +345,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.authenticating_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. diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java index db091300..8d95cdb8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java +++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java @@ -172,9 +172,11 @@ public class LeapSRPSession { * Calculates the parameter V of the SRP-6a algorithm. * @return the value of V */ - public BigInteger calculateV() { + public BigInteger calculateV(String username, String password, byte[] salt) { String k_string = "bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0"; BigInteger k = new BigInteger(k_string, 16); + byte[] x_bytes = calculatePasswordHash(username, password, ConfigHelper.trim(salt)); + x = new BigInteger(1, x_bytes); BigInteger v = k.multiply(g.modPow(x, N)); // g^x % N return v; } @@ -226,11 +228,8 @@ public class LeapSRPSession { // 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 - this.v = calculateV(); + this.v = calculateV(username, password, salt_bytes); // H(N) byte[] digest_of_n = newDigest().digest(N_bytes); 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..601df843 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/SignUpDialog.java @@ -0,0 +1,150 @@ +/** + * 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 . + */ + 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(); + } + }); + + return builder.create(); + } + + /** + * Interface used to communicate SignUpDialog with Dashboard. + * + * @author parmegv + * + */ + public interface SignUpDialogInterface { + /** + * Starts authentication process. + * @param username + * @param password + */ + public void signUp(String username, String password); + public void cancelAuthedEipOn(); + } + + 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..d4e9c879 100644 --- a/app/src/main/res/menu/client_dashboard.xml +++ b/app/src/main/res/menu/client_dashboard.xml @@ -6,18 +6,21 @@ + android:title="@string/switch_provider_menu_option"/> + - + android:visible="false"/> - + android:visible="false"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 492c48c7..5f0e2120 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -116,6 +116,7 @@ Update the app Log In Log Out + Sign Up Configuration Error Configure Exit -- cgit v1.2.3