From 112be4f505bd46d74eccc6a344ce1402a32957c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Sat, 10 Aug 2013 10:02:43 +0200 Subject: Replaced Apache HTTP client with HttpURLConnection I do not manually manage cookies anymore, letting HttpURLConnection manage them via default CookieHandler (using CookiePolicy.ACCEPT_ORIGINAL_SERVER). --- src/se/leap/leapclient/ProviderAPI.java | 207 ++++++++++++++++++++------------ 1 file changed, 127 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index d4402aa5..0b3e6f45 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -16,15 +16,20 @@ */ package se.leap.leapclient; -import java.io.BufferedInputStream; +import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.math.BigInteger; +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.CookiePolicy; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLConnection; +import java.net.URLEncoder; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; @@ -36,7 +41,6 @@ import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Scanner; @@ -49,14 +53,7 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.cookie.Cookie; -import org.apache.http.impl.client.DefaultHttpClient; import org.jboss.security.srp.SRPParameters; import org.json.JSONException; import org.json.JSONObject; @@ -104,6 +101,7 @@ public class ProviderAPI extends IntentService { public void onCreate() { super.onCreate(); mHandler = new Handler(); + CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER) ); } private void displayToast(final int toast_string_id) { @@ -246,6 +244,15 @@ public class ProviderAPI extends IntentService { session_id_bundle.putBoolean(ConfigHelper.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(ConfigHelper.USERNAME_KEY, 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 { session_id_bundle.putBoolean(ConfigHelper.RESULT_KEY, false); @@ -274,12 +281,19 @@ public class ProviderAPI extends IntentService { * @throws ClientProtocolException * @throws IOException * @throws JSONException + * @throws CertificateException + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws KeyManagementException */ - private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException { + private JSONObject sendAToSRPServer(String server_url, String username, String clientA) throws ClientProtocolException, IOException, JSONException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { Map parameters = new HashMap(); parameters.put("login", username); parameters.put("A", clientA); return sendToServer(server_url + "/sessions.json", "POST", parameters); + + /*HttpPost post = new HttpPost(server_url + "/sessions.json" + "?" + "login=" + username + "&&" + "A=" + clientA); + return sendToServer(post);*/ } /** @@ -291,10 +305,17 @@ public class ProviderAPI extends IntentService { * @throws ClientProtocolException * @throws IOException * @throws JSONException + * @throws CertificateException + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws KeyManagementException */ - 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, ConfigHelper.trim(m1)).toString(16)); - JSONObject json_response = sendToServer(put); + private JSONObject sendM1ToSRPServer(String server_url, String username, byte[] m1) throws ClientProtocolException, IOException, JSONException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { + 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) { @@ -307,30 +328,6 @@ 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(); - localContext.setAttribute(ClientContext.COOKIE_STORE, client.getCookieStore());*/ - - HttpResponse getResponse = client.execute(request/*, localContext*/); - HttpEntity responseEntity = getResponse.getEntity(); - String plain_response = new Scanner(responseEntity.getContent()).useDelimiter("\\A").next(); - JSONObject json_response = new JSONObject(plain_response); - if(!json_response.isNull(ConfigHelper.ERRORS_KEY) || json_response.has(ConfigHelper.ERRORS_KEY)) { - return new JSONObject(); - } - - return json_response; - } - /** * Executes an HTTP request expecting a JSON response. * @param url @@ -340,32 +337,64 @@ public class ProviderAPI extends IntentService { * @throws IOException * @throws JSONException * @throws MalformedURLException + * @throws CertificateException + * @throws NoSuchAlgorithmException + * @throws KeyStoreException + * @throws KeyManagementException */ - private JSONObject sendToServer(String url, String request_method, Map parameters) throws JSONException, MalformedURLException, IOException { + private JSONObject sendToServer(String url, String request_method, Map parameters) throws JSONException, MalformedURLException, IOException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException { JSONObject json_response; + InputStream is = null; HttpsURLConnection urlConnection = (HttpsURLConnection)new URL(url).openConnection(); + urlConnection.setRequestMethod(request_method); + urlConnection.setChunkedStreamingMode(0); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); try { - urlConnection.setRequestMethod(request_method); - Iterator parameter_iterator = parameters.keySet().iterator(); - while(parameter_iterator.hasNext()) { - String key = parameter_iterator.next(); - urlConnection.addRequestProperty(key, parameters.get(key)); - } - //urlConnection.setChunkedStreamingMode(0); + + DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream()); + writer.writeBytes(formatHttpParameters(parameters)); + writer.close(); - InputStream in = new BufferedInputStream(urlConnection.getInputStream()); - String plain_response = new Scanner(in).useDelimiter("\\A").next(); + is = urlConnection.getInputStream(); + String plain_response = new Scanner(is).useDelimiter("\\A").next(); json_response = new JSONObject(plain_response); - if(!json_response.isNull(ConfigHelper.ERRORS_KEY) || json_response.has(ConfigHelper.ERRORS_KEY)) { - return new JSONObject(); - } } finally { - urlConnection.disconnect(); + 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(ConfigHelper.ERRORS_KEY) || json_response.has(ConfigHelper.ERRORS_KEY)) { + return new JSONObject(); + } + } } return json_response; } + + private String formatHttpParameters(Map parameters) throws UnsupportedEncodingException { + StringBuilder result = new StringBuilder(); + boolean first = true; + + Iterator parameter_iterator = parameters.keySet().iterator(); + while(parameter_iterator.hasNext()) { + if(first) + first = false; + else + result.append("&&"); + + String key = parameter_iterator.next(); + String value = parameters.get(key); + + result.append(URLEncoder.encode(key, "UTF-8")); + result.append("="); + result.append(URLEncoder.encode(value, "UTF-8")); + } + return result.toString(); + } /** * 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. @@ -487,30 +516,11 @@ public class ProviderAPI extends IntentService { private String downloadWithProviderCA(URL url, boolean danger_on) { String json_file_content = ""; - String provider_cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); - try { - java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); - - // Create a KeyStore containing our trusted CAs - String keyStoreType = KeyStore.getDefaultType(); - KeyStore keyStore = KeyStore.getInstance(keyStoreType); - keyStore.load(null, null); - keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); - - // Create a TrustManager that trusts the CAs in our KeyStore - String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); - tmf.init(keyStore); - - // Create an SSLContext that uses our TrustManager - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, tmf.getTrustManagers(), null); - // Tell the URLConnection to use a SocketFactory from our SSLContext HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection(); - urlConnection.setSSLSocketFactory(context.getSocketFactory()); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); json_file_content = new Scanner(urlConnection.getInputStream()).useDelimiter("\\A").next(); } catch (CertificateException e) { // TODO Auto-generated catch block @@ -540,6 +550,29 @@ public class ProviderAPI extends IntentService { return json_file_content; } + private javax.net.ssl.SSLSocketFactory getProviderSSLSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException { + String provider_cert_string = ConfigHelper.getStringFromSharedPref(ConfigHelper.MAIN_CERT_KEY); + + java.security.cert.Certificate provider_certificate = ConfigHelper.parseX509CertificateFromString(provider_cert_string); + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry("provider_ca_certificate", provider_certificate); + + // Create a TrustManager that trusts the CAs in our KeyStore + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init(keyStore); + + // Create an SSLContext that uses our TrustManager + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, tmf.getTrustManagers(), null); + + return context.getSocketFactory(); + } + /** * Downloads the string that's in the url with any certificate. */ @@ -608,13 +641,15 @@ public class ProviderAPI extends IntentService { * @return true if there were no exceptions */ private boolean logOut(Bundle task) { - DefaultHttpClient client = LeapHttpClient.getInstance(getApplicationContext()); try { String delete_url = task.getString(ConfigHelper.API_URL_KEY) + "/logout"; - HttpDelete delete = new HttpDelete(delete_url); - HttpResponse getResponse = client.execute(delete); - HttpEntity responseEntity = getResponse.getEntity(); - responseEntity.consumeContent(); + + HttpsURLConnection urlConnection = (HttpsURLConnection)new URL(delete_url).openConnection(); + urlConnection.setRequestMethod("DELETE"); + urlConnection.setSSLSocketFactory(getProviderSSLSocketFactory()); + + int responseCode = urlConnection.getResponseCode(); + Log.d("logout", Integer.toString(responseCode)); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -627,6 +662,18 @@ public class ProviderAPI extends IntentService { // TODO Auto-generated catch block e.printStackTrace(); return false; + } catch (KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } return true; } @@ -638,13 +685,13 @@ public class ProviderAPI extends IntentService { * @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); + //String type_of_certificate = task.getString(ConfigHelper.TYPE_OF_CERTIFICATE); try { JSONObject provider_json = ConfigHelper.getJsonFromSharedPref(ConfigHelper.PROVIDER_KEY); URL provider_main_url = new URL(provider_json.getString(ConfigHelper.API_URL_KEY)); String new_cert_string_url = provider_main_url.toString() + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.CERT_KEY; - Cookie cookie = null; + /*Cookie cookie = null; if(type_of_certificate.equalsIgnoreCase(ConfigHelper.AUTHED_CERTIFICATE)) { List list_cookies = LeapHttpClient.getInstance(getApplicationContext()).getCookieStore().getCookies(); for(Cookie aux_cookie : list_cookies) { @@ -652,14 +699,14 @@ public class ProviderAPI extends IntentService { cookie = aux_cookie; break; } - } + }*/ //HttpCookie session_id_cookie = new HttpCookie(task.getString(ConfigHelper.SESSION_ID_COOKIE_KEY), task.getString(ConfigHelper.SESSION_ID_KEY)); /*HttpCookie session_id_cookie = new HttpCookie(cookie.getName(), cookie.getValue()); CookieManager cookieManager = new CookieManager(); cookieManager.getCookieStore().add(provider_main_url.toURI(), session_id_cookie); CookieHandler.setDefault(cookieManager);*/ - } + //} boolean danger_on = ConfigHelper.getBoolFromSharedPref(ConfigHelper.DANGER_ON); String cert_string = downloadWithCommercialCA(new_cert_string_url, danger_on); -- cgit v1.2.3