From 6d9770518b0d94931e9521b72131516a841b193f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 8 May 2014 09:51:53 +0200 Subject: Raw json error messages shown. A bit of refactoring too, sendM1 much simpler. --- .../java/se/leap/bitmaskclient/ProviderAPI.java | 306 ++++++++++----------- .../java/se/leap/bitmaskclient/LeapSRPSession.java | 5 +- 2 files changed, 150 insertions(+), 161 deletions(-) diff --git a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java index 89ba9135..8481bf08 100644 --- a/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java +++ b/app/src/debug/java/se/leap/bitmaskclient/ProviderAPI.java @@ -217,41 +217,19 @@ public class ProviderAPI extends IntentService { /* Calculate password verifier */ BigInteger password_verifier = client.calculateV(username, password, salt); /* Send to the server */ - try { - JSONObject result = sendNewUserDataToSRPServer(authentication_server, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); - 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(); - } catch (KeyStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + JSONObject result = sendNewUserDataToSRPServer(authentication_server, username, new BigInteger(1, salt).toString(16), password_verifier.toString(16)); + if(result.has(ERRORS)) { + session_id_bundle.putBoolean(RESULT_KEY, false); + try { + // {"errors":{"login":["has already been taken","has already been taken"]}} + session_id_bundle.putString(getResources().getString(R.string.user_message), result.getJSONObject(ERRORS).toString()); + session_id_bundle.putString(LogInDialog.USERNAME, username); + } catch(JSONException e) { + e.printStackTrace(); + } } - + Log.d(TAG, result.toString()); + broadcast_progress(progress++); } else { if(!wellFormedPassword(password)) { session_id_bundle.putBoolean(RESULT_KEY, false); @@ -273,88 +251,84 @@ public class ProviderAPI extends IntentService { * @return a bundle with a boolean value mapped to a key named RESULT_KEY, and which is true if authentication was successful. */ private Bundle authenticateBySRP(Bundle task) { - Bundle session_id_bundle = new Bundle(); - int progress = 0; + Bundle session_id_bundle = new Bundle(); + int progress = 0; - String username = (String) task.get(LogInDialog.USERNAME); - String password = (String) task.get(LogInDialog.PASSWORD); - if(validUserLoginData(username, password)) { + String username = (String) task.get(LogInDialog.USERNAME); + String password = (String) task.get(LogInDialog.PASSWORD); + if(validUserLoginData(username, password)) { - String authentication_server = (String) task.get(Provider.API_URL); + String authentication_server = (String) task.get(Provider.API_URL); + JSONObject authentication_step_result = new JSONObject(); - SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); - LeapSRPSession client = new LeapSRPSession(username, password, params); - byte[] A = client.exponential(); + SRPParameters params = new SRPParameters(new BigInteger(ConfigHelper.NG_1024, 16).toByteArray(), ConfigHelper.G.toByteArray(), BigInteger.ZERO.toByteArray(), "SHA-256"); + LeapSRPSession client = new LeapSRPSession(username, password, params); + byte[] A = client.exponential(); + broadcast_progress(progress++); + authentication_step_result = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); + try { + String salt = authentication_step_result.getString(LeapSRPSession.SALT); + broadcast_progress(progress++); + byte[] Bbytes = new BigInteger(authentication_step_result.getString("B"), 16).toByteArray(); + byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); + if(M1 != null) { broadcast_progress(progress++); - try { - JSONObject saltAndB = sendAToSRPServer(authentication_server, username, new BigInteger(1, A).toString(16)); - if(saltAndB.length() > 0) { - String salt = saltAndB.getString(LeapSRPSession.SALT); - broadcast_progress(progress++); - byte[] Bbytes = new BigInteger(saltAndB.getString("B"), 16).toByteArray(); - byte[] M1 = client.response(new BigInteger(salt, 16).toByteArray(), Bbytes); - if(M1 != null) { - broadcast_progress(progress++); - JSONObject session_idAndM2 = sendM1ToSRPServer(authentication_server, username, M1); - if(session_idAndM2.has(LeapSRPSession.M2) && client.verify((byte[])session_idAndM2.get(LeapSRPSession.M2))) { - session_id_bundle.putBoolean(RESULT_KEY, true); - broadcast_progress(progress++); - } else { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_bad_user_password_user_message)); - session_id_bundle.putString(LogInDialog.USERNAME, username); - } - } else { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); - } - broadcast_progress(progress++); - } else { - session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_bad_user_password_user_message)); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putBoolean(RESULT_KEY, false); - } - } 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); - } 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); - } 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); - } 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); - } catch (KeyManagementException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (KeyStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } else { - if(!wellFormedPassword(password)) { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putString(LogInDialog.USERNAME, username); - session_id_bundle.putBoolean(LogInDialog.PASSWORD_INVALID_LENGTH, true); - } - if(username.isEmpty()) { - session_id_bundle.putBoolean(RESULT_KEY, false); - session_id_bundle.putBoolean(LogInDialog.USERNAME_MISSING, true); + authentication_step_result = sendM1ToSRPServer(authentication_server, username, M1); + setTokenIfAvailable(authentication_step_result); + byte[] M2 = new BigInteger(authentication_step_result.getString(LeapSRPSession.M2), 16).toByteArray(); + if(client.verify(M2)) { + session_id_bundle.putBoolean(RESULT_KEY, true); + broadcast_progress(progress++); + } else { + authFailedNotification(authentication_step_result, username); } + } else { + session_id_bundle.putBoolean(RESULT_KEY, false); + session_id_bundle.putString(LogInDialog.USERNAME, username); + session_id_bundle.putString(getResources().getString(R.string.user_message), getResources().getString(R.string.error_srp_math_error_user_message)); + } + } catch (JSONException e) { + session_id_bundle = authFailedNotification(authentication_step_result, username); + e.printStackTrace(); + } + broadcast_progress(progress++); + } else { + if(!wellFormedPassword(password)) { + session_id_bundle.putBoolean(RESULT_KEY, false); + session_id_bundle.putString(LogInDialog.USERNAME, username); + session_id_bundle.putBoolean(LogInDialog.PASSWORD_INVALID_LENGTH, true); } + if(username.isEmpty()) { + session_id_bundle.putBoolean(RESULT_KEY, false); + session_id_bundle.putBoolean(LogInDialog.USERNAME_MISSING, true); + } + } - return session_id_bundle; + return session_id_bundle; } + + private boolean setTokenIfAvailable(JSONObject authentication_step_result) { + try { + LeapSRPSession.setToken(authentication_step_result.getString(LeapSRPSession.TOKEN)); + CookieHandler.setDefault(null); // we don't need cookies anymore + } catch(JSONException e) { // + return false; + } + return true; + } + + private Bundle authFailedNotification(JSONObject result, String username) { + Log.d(TAG, "authFailedNotification("+ result +")"); + Bundle user_notification_bundle = new Bundle(); + try{ + user_notification_bundle.putString(getResources().getString(R.string.user_message), result.getJSONObject(ERRORS).toString()); + } catch(JSONException e) {} + if(!username.isEmpty()) + user_notification_bundle.putString(LogInDialog.USERNAME, username); + user_notification_bundle.putBoolean(RESULT_KEY, false); + + return user_notification_bundle; + } /** * Sets up an intent with the progress value passed as a parameter @@ -402,7 +376,7 @@ public class ProviderAPI extends IntentService { * @throws KeyStoreException * @throws KeyManagementException */ - private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { + private JSONObject sendAToSRPServer(String server_url, String username, String clientA) { Map parameters = new HashMap(); parameters.put("login", username); parameters.put("A", clientA); @@ -426,25 +400,11 @@ public class ProviderAPI extends IntentService { * @throws KeyStoreException * @throws KeyManagementException */ - private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { + private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) { Map parameters = new HashMap(); parameters.put("client_auth", new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); - //HttpPut put = new HttpPut(server_url + "/sessions/" + username +".json" + "?" + "client_auth" + "=" + new BigInteger(1, ConfigHelper.trim(m1)).toString(16)); - JSONObject json_response = sendToServer(server_url + "/sessions/" + username +".json", "PUT", parameters); - - JSONObject session_idAndM2 = new JSONObject(); - if(json_response.length() > 0) { - byte[] M2_not_trimmed = new BigInteger(json_response.getString(LeapSRPSession.M2), 16).toByteArray(); - /*Cookie session_id_cookie = LeapHttpClient.getInstance(getApplicationContext()).getCookieStore().getCookies().get(0); - session_idAndM2.put(ConfigHelper.SESSION_ID_COOKIE_KEY, session_id_cookie.getName()); - session_idAndM2.put(ConfigHelper.SESSION_ID_KEY, session_id_cookie.getValue());*/ - session_idAndM2.put(LeapSRPSession.M2, ConfigHelper.trim(M2_not_trimmed)); - CookieHandler.setDefault(null); // we don't need cookies anymore - String token = json_response.getString(LeapSRPSession.TOKEN); - LeapSRPSession.setToken(token); - } - return session_idAndM2; + return sendToServer(server_url + "/sessions/" + username +".json", "PUT", parameters); } /** @@ -462,15 +422,15 @@ public class ProviderAPI extends IntentService { * @throws KeyStoreException * @throws KeyManagementException */ - private JSONObject sendNewUserDataToSRPServer(String server_url, String username, String salt, String password_verifier) throws ClientProtocolException, IOException, JSONException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { - Map parameters = new HashMap(); - parameters.put("user[login]", username); - parameters.put("user[password_salt]", salt); - parameters.put("user[password_verifier]", password_verifier); - Log.d(TAG, server_url); - Log.d(TAG, parameters.toString()); - return sendToServer(server_url + "/users", "POST", parameters); - } + private JSONObject sendNewUserDataToSRPServer(String server_url, String username, String salt, String password_verifier) { + Map parameters = new HashMap(); + parameters.put("user[login]", username); + parameters.put("user[password_salt]", salt); + parameters.put("user[password_verifier]", password_verifier); + Log.d(TAG, server_url); + Log.d(TAG, parameters.toString()); + return sendToServer(server_url + "/users", "POST", parameters); + } /** * Executes an HTTP request expecting a JSON response. @@ -486,37 +446,67 @@ public class ProviderAPI extends IntentService { * @throws KeyStoreException * @throws KeyManagementException */ - private JSONObject sendToServer(String url, String request_method, Map parameters) throws JSONException, MalformedURLException, IOException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { - JSONObject json_response; + private JSONObject sendToServer(String url, String request_method, Map parameters) { + JSONObject json_response; + HttpsURLConnection urlConnection = null; + try { InputStream is = null; - HttpsURLConnection urlConnection = (HttpsURLConnection)new URL(url).openConnection(); + urlConnection = (HttpsURLConnection)new URL(url).openConnection(); urlConnection.setRequestMethod(request_method); urlConnection.setChunkedStreamingMode(0); urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + + DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); + writer.writeBytes(formatHttpParameters(parameters)); + writer.close(); + + is = urlConnection.getInputStream(); + String plain_response = new Scanner(is).useDelimiter("\\A").next(); + json_response = new JSONObject(plain_response); + } catch (ClientProtocolException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (IOException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (JSONException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (KeyManagementException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (KeyStoreException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } catch (CertificateException e) { + json_response = getErrorMessage(urlConnection); + e.printStackTrace(); + } + + return json_response; + } + + private JSONObject getErrorMessage(HttpsURLConnection urlConnection) { + JSONObject error_message = new JSONObject(); + if(urlConnection != null) { + InputStream error_stream = urlConnection.getErrorStream(); + if(error_stream != null) { + String error_response = new Scanner(error_stream).useDelimiter("\\A").next(); + Log.d("Error", error_response); try { - - DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); - writer.writeBytes(formatHttpParameters(parameters)); - writer.close(); - - is = urlConnection.getInputStream(); - String plain_response = new Scanner(is).useDelimiter("\\A").next(); - json_response = new JSONObject(plain_response); - } finally { - InputStream error_stream = urlConnection.getErrorStream(); - if(error_stream != null) { - String error_response = new Scanner(error_stream).useDelimiter("\\A").next(); - urlConnection.disconnect(); - Log.d("Error", error_response); - json_response = new JSONObject(error_response); - if(!json_response.isNull(ERRORS) || json_response.has(ERRORS)) { - return new JSONObject(); - } - } + error_message = new JSONObject(error_response); + } catch (JSONException e) { + Log.d(TAG, e.getMessage()); + e.printStackTrace(); } - - return json_response; + urlConnection.disconnect(); + } } + return error_message; + } private String formatHttpParameters(Map parameters) throws UnsupportedEncodingException { StringBuilder result = new StringBuilder(); diff --git a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java index f8279b64..29b429d1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java +++ b/app/src/main/java/se/leap/bitmaskclient/LeapSRPSession.java @@ -219,7 +219,7 @@ 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) { @@ -257,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 -- cgit v1.2.3