1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 package eu
.alefzero
.owncloud
.authenticator
;
21 import java
.io
.IOException
;
22 import java
.net
.MalformedURLException
;
24 import java
.net
.UnknownHostException
;
25 import java
.security
.KeyManagementException
;
26 import java
.security
.KeyStore
;
27 import java
.security
.KeyStoreException
;
28 import java
.security
.NoSuchAlgorithmException
;
29 import java
.security
.SecureRandom
;
30 import java
.security
.UnrecoverableKeyException
;
32 import javax
.net
.SocketFactory
;
33 import javax
.net
.ssl
.HostnameVerifier
;
34 import javax
.net
.ssl
.HttpsURLConnection
;
35 import javax
.net
.ssl
.SSLContext
;
36 import javax
.net
.ssl
.SSLSession
;
37 import javax
.net
.ssl
.TrustManager
;
38 import javax
.net
.ssl
.X509TrustManager
;
40 import javax
.security
.cert
.CertificateException
;
41 import javax
.security
.cert
.X509Certificate
;
43 import org
.apache
.http
.client
.HttpClient
;
44 import org
.apache
.http
.conn
.ClientConnectionManager
;
45 import org
.apache
.http
.conn
.scheme
.Scheme
;
46 import org
.apache
.http
.conn
.scheme
.SchemeRegistry
;
48 import org
.apache
.http
.impl
.client
.DefaultHttpClient
;
50 import org
.apache
.commons
.httpclient
.auth
.BasicScheme
;
51 import org
.apache
.http
.HttpHost
;
52 import org
.apache
.http
.HttpResponse
;
53 import org
.apache
.http
.HttpVersion
;
54 import org
.apache
.http
.auth
.AuthScope
;
55 import org
.apache
.http
.auth
.UsernamePasswordCredentials
;
56 import org
.apache
.http
.client
.ClientProtocolException
;
57 import org
.apache
.http
.client
.methods
.HttpHead
;
58 import org
.apache
.http
.conn
.params
.ConnManagerPNames
;
59 import org
.apache
.http
.conn
.params
.ConnPerRouteBean
;
60 import org
.apache
.http
.conn
.scheme
.PlainSocketFactory
;
61 import org
.apache
.http
.conn
.ssl
.SSLSocketFactory
;
62 import org
.apache
.http
.impl
.conn
.SingleClientConnManager
;
63 import org
.apache
.http
.impl
.conn
.tsccm
.ThreadSafeClientConnManager
;
64 import org
.apache
.http
.params
.BasicHttpParams
;
65 import org
.apache
.http
.params
.HttpParams
;
66 import org
.apache
.http
.params
.HttpProtocolParams
;
67 import org
.apache
.http
.protocol
.BasicHttpContext
;
69 import eu
.alefzero
.owncloud
.ui
.activity
.AuthenticatorActivity
;
72 import android
.content
.Context
;
73 import android
.os
.Handler
;
74 import android
.util
.Log
;
76 public class AuthUtils
{
77 public static final String WEBDAV_PATH_1_2
= "/webdav/owncloud.php";
78 public static final String WEBDAV_PATH_2_0
= "/files/webdav.php";
79 public static final String CARDDAV_PATH_2_0
= "/apps/contacts/carddav.php";
81 private static String mResultMsg
= "";
83 public static boolean authenticate(URL url
, String username
, String password
,
84 Handler handler
, Context context
) {
85 String strippedPath
= url
.toString().endsWith("/") ?
86 url
.toString().substring(0, url
.toString().length()-1) :
88 String webdatPath
= strippedPath
+ WEBDAV_PATH_2_0
;
89 URL complete_url
= null
;
91 complete_url
= new URL(webdatPath
);
92 } catch (MalformedURLException e
) {
93 // should never happend
94 sendResult(false
, handler
, context
, "URL error");
98 // version 2.0 success
99 if (tryGetWebdav(complete_url
, username
, password
, handler
, context
)) {
100 sendResult(true
, handler
, context
, complete_url
.toString());
104 if (mResultMsg
.equals("401")) {
105 sendResult(false
, handler
, context
, "Invalid login or/and password");
109 if (!mResultMsg
.equals("404")) {
110 sendResult(false
, handler
, context
, "Server error: " + mResultMsg
);
114 webdatPath
= strippedPath
+ WEBDAV_PATH_1_2
;
116 complete_url
= new URL(webdatPath
);
117 } catch (MalformedURLException e
) {
118 // should never happend
119 sendResult(false
, handler
, context
, "URL error");
123 // version 1.2 success
124 if (tryGetWebdav(complete_url
, username
, password
, handler
, context
)) {
125 sendResult(true
, handler
, context
, complete_url
.toString());
129 if (mResultMsg
.equals("401")) {
130 sendResult(false
, handler
, context
, "Invalid login or/and password");
134 if (mResultMsg
.equals("404")) {
135 sendResult(false
, handler
, context
, "Wrong path given");
139 sendResult(false
, handler
, context
, "Server error: " + mResultMsg
);
143 public static boolean tryGetWebdav(URL url
, String username
, String pwd
,
144 Handler handler
, Context context
) {
145 SchemeRegistry schemeRegistry
= new SchemeRegistry();
147 schemeRegistry
.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
149 schemeRegistry
.register(new Scheme("https", new EasySSLSocketFactory(), 443));
151 HttpParams params
= new BasicHttpParams();
152 params
.setParameter(ConnManagerPNames
.MAX_TOTAL_CONNECTIONS
, 30);
153 params
.setParameter(ConnManagerPNames
.MAX_CONNECTIONS_PER_ROUTE
, new ConnPerRouteBean(30));
154 params
.setParameter(HttpProtocolParams
.USE_EXPECT_CONTINUE
, false
);
155 HttpProtocolParams
.setVersion(params
, HttpVersion
.HTTP_1_1
);
157 ClientConnectionManager cm
= new ThreadSafeClientConnManager(params
, schemeRegistry
);
159 DefaultHttpClient c
= new DefaultHttpClient(cm
, params
);
161 c
.getCredentialsProvider().setCredentials(
162 new AuthScope(url
.getHost(), (url
.getPort() == -1)?
80:url
.getPort()),
163 new UsernamePasswordCredentials(username
, pwd
));
165 BasicHttpContext localcontext
= new BasicHttpContext();
166 BasicScheme basicAuth
= new BasicScheme();
168 localcontext
.setAttribute("preemptive-auth", basicAuth
);
169 HttpHost targetHost
= new HttpHost(url
.getHost(), (url
.getPort() == -1)
171 : url
.getPort(), (url
.getProtocol().equals("https")) ?
"https" : "http");
172 HttpHead httpget
= new HttpHead(url
.toString());
173 httpget
.setHeader("Host", url
.getHost());
174 HttpResponse response
= null
;
176 response
= c
.execute(targetHost
, httpget
, localcontext
);
177 } catch (ClientProtocolException e1
) {
178 sendResult(false
, handler
, context
, "Protocol error: "
179 + e1
.getLocalizedMessage());
181 } catch (UnknownHostException e1
) {
182 mResultMsg
= "Unknowh host: " + e1
.getLocalizedMessage();
184 } catch (IOException e1
) {
185 mResultMsg
= "Error: " + e1
.getLocalizedMessage();
188 String status
= response
.getStatusLine().toString();
190 status
= status
.split(" ")[1];
191 Log
.i("AuthUtils", "Status returned: " + status
);
192 if (status
.equals("200")) {
194 } else if (status
.equals("404")) {
197 } else if (status
.equals("401")) {
205 public static Thread
performOnBackgroundThread(final Runnable r
) {
206 final Thread t
= new Thread() {
218 public static void sendResult(final Boolean result
,
219 final Handler handler
,
220 final Context context
,
221 final String message
) {
222 if (handler
== null
|| context
== null
) {
225 handler
.post(new Runnable() {
227 ((AuthenticatorActivity
) context
).onAuthenticationResult(result
, message
);
232 public static Thread
attemptAuth(final URL url
, final String username
,
233 final String password
, final Handler handler
,
234 final Context context
) {
235 final Runnable r
= new Runnable() {
238 authenticate(url
, username
, password
, handler
, context
);
241 return performOnBackgroundThread(r
);