diff --git a/src/main/java/fr/unix_experience/owncloud_sms/activities/LoginActivity.java b/src/main/java/fr/unix_experience/owncloud_sms/activities/LoginActivity.java
index 3799e1d..a5ca51c 100644
--- a/src/main/java/fr/unix_experience/owncloud_sms/activities/LoginActivity.java
+++ b/src/main/java/fr/unix_experience/owncloud_sms/activities/LoginActivity.java
@@ -48,7 +48,7 @@ import java.io.IOException;
import fr.unix_experience.owncloud_sms.R;
import fr.unix_experience.owncloud_sms.defines.DefaultPrefs;
-import fr.unix_experience.owncloud_sms.engine.HTTPRequestBuilder;
+import fr.unix_experience.owncloud_sms.engine.OCHttpClient;
/**
* A login screen that offers login via email/password.
@@ -241,7 +241,7 @@ public class LoginActivity extends AppCompatActivity {
@Override
protected Boolean doInBackground(Void... params) {
_returnCode = 0;
- HTTPRequestBuilder http = new HTTPRequestBuilder(_serverURI, _login, _password);
+ OCHttpClient http = new OCHttpClient(_serverURI, _login, _password);
GetMethod testMethod = http.getVersion();
try {
_returnCode = http.execute(testMethod);
diff --git a/src/main/java/fr/unix_experience/owncloud_sms/engine/HTTPRequestBuilder.java b/src/main/java/fr/unix_experience/owncloud_sms/engine/OCHttpClient.java
similarity index 74%
rename from src/main/java/fr/unix_experience/owncloud_sms/engine/HTTPRequestBuilder.java
rename to src/main/java/fr/unix_experience/owncloud_sms/engine/OCHttpClient.java
index 0ba2a74..8d05d49 100644
--- a/src/main/java/fr/unix_experience/owncloud_sms/engine/HTTPRequestBuilder.java
+++ b/src/main/java/fr/unix_experience/owncloud_sms/engine/OCHttpClient.java
@@ -23,15 +23,19 @@ import android.util.Log;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import java.io.IOException;
-public class HTTPRequestBuilder {
+public class OCHttpClient extends HttpClient {
- private static final String TAG = HTTPRequestBuilder.class.getCanonicalName();
+ private static final String TAG = OCHttpClient.class.getCanonicalName();
private final Uri _serverURI;
private final String _username;
private final String _password;
@@ -48,47 +52,49 @@ public class HTTPRequestBuilder {
private static final String OC_V2_GET_MESSAGES_PHONE ="/index.php/apps/ocsms/api/v2/messages/[PHONENUMBER]/[START]/[LIMIT]?format=json";
private static final String OC_V2_GET_MESSAGES_SENDQUEUE = "/index.php/apps/ocsms/api/v2/messages/sendqueue?format=json";
- public HTTPRequestBuilder(Uri serverURI, String accountName, String accountPassword) {
+ public OCHttpClient(Uri serverURI, String accountName, String accountPassword) {
+ super(new MultiThreadedHttpConnectionManager());
+ Protocol easyhttps = new Protocol("https", (ProtocolSocketFactory)new EasySSLProtocolSocketFactory(), 443);
+ Protocol.registerProtocol("https", easyhttps);
_serverURI = serverURI;
_username = accountName;
_password = accountPassword;
}
private GetMethod get(String oc_call) {
- Log.i(HTTPRequestBuilder.TAG, "Create GET " + _serverURI + oc_call);
+ Log.i(OCHttpClient.TAG, "Create GET " + _serverURI + oc_call);
return new GetMethod(_serverURI.toString() + oc_call);
}
GetMethod getAllSmsIds() {
- return get(HTTPRequestBuilder.OC_GET_ALL_SMS_IDS);
+ return get(OCHttpClient.OC_GET_ALL_SMS_IDS);
}
public GetMethod getVersion() {
- return get(HTTPRequestBuilder.OC_GET_VERSION);
+ return get(OCHttpClient.OC_GET_VERSION);
}
PostMethod pushSms(StringRequestEntity ent) {
- PostMethod post = new PostMethod(_serverURI.toString() + HTTPRequestBuilder.OC_PUSH_ROUTE);
+ PostMethod post = new PostMethod(_serverURI.toString() + OCHttpClient.OC_PUSH_ROUTE);
post.setRequestEntity(ent);
return post;
}
GetMethod getPhoneList() {
- return get(HTTPRequestBuilder.OC_V2_GET_PHONELIST);
+ return get(OCHttpClient.OC_V2_GET_PHONELIST);
}
GetMethod getMessages(Long start, Integer limit) {
- return get(HTTPRequestBuilder.OC_V2_GET_MESSAGES.
+ return get(OCHttpClient.OC_V2_GET_MESSAGES.
replace("[START]", start.toString()).replace("[LIMIT]", limit.toString()));
}
public int execute(HttpMethod req) throws IOException {
- HttpClient http = new HttpClient();
String basicAuth = "Basic " +
Base64.encodeToString((_username + ":" + _password).getBytes(), Base64.NO_WRAP);
//req.setFollowRedirects(true); // App is SIGKILLED by android when doing this... WTF
req.setDoAuthentication(true);
req.addRequestHeader("Authorization", basicAuth);
- return http.executeMethod(req);
+ return executeMethod(req);
}
}
diff --git a/src/main/java/fr/unix_experience/owncloud_sms/engine/OCSMSOwnCloudClient.java b/src/main/java/fr/unix_experience/owncloud_sms/engine/OCSMSOwnCloudClient.java
index 517462c..2a58aed 100644
--- a/src/main/java/fr/unix_experience/owncloud_sms/engine/OCSMSOwnCloudClient.java
+++ b/src/main/java/fr/unix_experience/owncloud_sms/engine/OCSMSOwnCloudClient.java
@@ -56,7 +56,7 @@ public class OCSMSOwnCloudClient {
}
Uri serverURI = Uri.parse(ocURI);
- _http = new HTTPRequestBuilder(serverURI, accountManager.getUserData(account, "ocLogin"),
+ _http = new OCHttpClient(serverURI, accountManager.getUserData(account, "ocLogin"),
accountManager.getPassword(account));
_connectivityMonitor = new ConnectivityMonitor(_context);
}
@@ -369,7 +369,7 @@ public class OCSMSOwnCloudClient {
private static final int maximumHttpReqTries = 3;
- private final HTTPRequestBuilder _http;
+ private final OCHttpClient _http;
private final Context _context;
private final ConnectivityMonitor _connectivityMonitor;
diff --git a/src/main/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java b/src/main/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java
new file mode 100644
index 0000000..beb95c3
--- /dev/null
+++ b/src/main/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java
@@ -0,0 +1,224 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s + * that accept self-signed certificates. + *
+ *+ * This socket factory SHOULD NOT be used for productive systems + * due to security reasons, unless it is a concious decision and + * you are perfectly aware of security implications of accepting + * self-signed certificates + *
+ * + *+ * Example of using custom protocol socket factory for a specific host: + *
+ * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); + * + * URI uri = new URI("https://localhost/", true); + * // use relative url only + * GetMethod httpget = new GetMethod(uri.getPathQuery()); + * HostConfiguration hc = new HostConfiguration(); + * hc.setHost(uri.getHost(), uri.getPort(), easyhttps); + * HttpClient client = new HttpClient(); + * client.executeMethod(hc, httpget); + *+ * + *
+ * Example of using custom protocol socket factory per default instead of the standard one: + *
+ * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); + * Protocol.registerProtocol("https", easyhttps); + * + * HttpClient client = new HttpClient(); + * GetMethod httpget = new GetMethod("https://localhost/"); + * client.executeMethod(httpget); + *+ * + * + * @author Oleg Kalnichevski + * + *
+ * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *
+ */ + +public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory { + + private SSLContext sslcontext = null; + + /** + * Constructor for EasySSLProtocolSocketFactory. + */ + public EasySSLProtocolSocketFactory() { + super(); + } + + private static SSLContext createEasySSLContext() { + try { + SSLContext context = SSLContext.getInstance("SSL"); + context.init( + null, + new TrustManager[] {new EasyX509TrustManager(null)}, + null); + return context; + } catch (Exception e) { + throw new HttpClientError(e.toString()); + } + } + + private SSLContext getSSLContext() { + if (this.sslcontext == null) { + this.sslcontext = createEasySSLContext(); + } + return this.sslcontext; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket( + String host, + int port, + InetAddress clientHost, + int clientPort) + throws IOException, UnknownHostException { + + return getSSLContext().getSocketFactory().createSocket( + host, + port, + clientHost, + clientPort + ); + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *+ * To circumvent the limitations of older JREs that do not support connect timeout a + * controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the + * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException} + *
+ * + * @param host the host name/IP + * @param port the port on the host + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + SocketFactory socketfactory = getSSLContext().getSocketFactory(); + if (timeout == 0) { + return socketfactory.createSocket(host, port, localAddress, localPort); + } else { + Socket socket = socketfactory.createSocket(); + SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); + SocketAddress remoteaddr = new InetSocketAddress(host, port); + socket.bind(localaddr); + socket.connect(remoteaddr, timeout); + return socket; + } + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket( + host, + port + ); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket( + Socket socket, + String host, + int port, + boolean autoClose) + throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket( + socket, + host, + port, + autoClose + ); + } + + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class)); + } + + public int hashCode() { + return EasySSLProtocolSocketFactory.class.hashCode(); + } + +} diff --git a/src/main/java/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java b/src/main/java/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java new file mode 100644 index 0000000..f566f5a --- /dev/null +++ b/src/main/java/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java @@ -0,0 +1,103 @@ +/* + * ==================================================================== + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *+ * EasyX509TrustManager unlike default {@link X509TrustManager} accepts + * self-signed certificates. + *
+ *+ * This trust manager SHOULD NOT be used for productive systems + * due to security reasons, unless it is a concious decision and + * you are perfectly aware of security implications of accepting + * self-signed certificates + *
+ * + * @author Adrian Sutton + * @author Oleg Kalnichevski + * + *+ * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *
+ */ + +public class EasyX509TrustManager implements X509TrustManager +{ + private X509TrustManager standardTrustManager = null; + + /** + * Constructor for EasyX509TrustManager. + */ + public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { + super(); + TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + factory.init(keystore); + TrustManager[] trustmanagers = factory.getTrustManagers(); + if (trustmanagers.length == 0) { + throw new NoSuchAlgorithmException("no trust manager found"); + } + this.standardTrustManager = (X509TrustManager)trustmanagers[0]; + } + + /** + * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType) + */ + public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + standardTrustManager.checkClientTrusted(certificates,authType); + } + + /** + * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType) + */ + public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + if ((certificates != null) && (certificates.length == 1)) { + certificates[0].checkValidity(); + } else { + standardTrustManager.checkServerTrusted(certificates,authType); + } + } + + /** + * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() + */ + public X509Certificate[] getAcceptedIssuers() { + return this.standardTrustManager.getAcceptedIssuers(); + } +}