1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-23 09:52:16 -05:00

self-signed cert support for WebDav.

This commit is contained in:
Bradley Young 2009-01-05 00:05:43 +00:00
parent 1a7539af1d
commit 8221094570
3 changed files with 107 additions and 76 deletions

View File

@ -107,7 +107,6 @@ public final class TrustManagerFactory {
Application app = Email.app;
keyStoreFile = new File(app.getDir("KeyStore", Context.MODE_PRIVATE) + File.separator + "KeyStore.bks");
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
//TODO: read store from disk.
java.io.FileInputStream fis;
try {
fis = new java.io.FileInputStream(keyStoreFile);
@ -116,6 +115,9 @@ public final class TrustManagerFactory {
}
try {
keyStore.load(fis, "".toCharArray());
//if (fis != null) {
// fis.close();
//}
} catch (IOException e) {
Log.e(LOG_TAG, "KeyStore IOException while initializing TrustManagerFactory ", e);
keyStore = null;

View File

@ -1,39 +1,51 @@
package com.android.email.mail.store;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Stack;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
import com.android.email.Email;
import com.android.email.mail.CertificateValidationException;
@ -44,37 +56,9 @@ import com.android.email.mail.Message;
import com.android.email.mail.MessageRetrievalListener;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import com.android.email.mail.internet.MimeBodyPart;
import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.internet.TextBody;
import com.android.email.mail.transport.EOLConvertingOutputStream;
import com.android.email.mail.transport.TrustedSocketFactory;
import org.apache.http.HttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* <pre>
* Uses WebDAV formatted HTTP calls to an MS Exchange server to fetch emails
@ -107,7 +91,8 @@ public class WebDavStore extends Store {
private HashMap<String, WebDavFolder> mFolderList = new HashMap<String, WebDavFolder>();
private boolean mSecure;
private DefaultHttpClient mHttpClient = null;
/**
* webdav://user:password@server:port CONNECTION_SECURITY_NONE
* webdav+tls://user:password@server:port CONNECTION_SECURITY_TLS_OPTIONAL
@ -150,9 +135,9 @@ public class WebDavStore extends Store {
mConnectionSecurity == CONNECTION_SECURITY_SSL_REQUIRED ||
mConnectionSecurity == CONNECTION_SECURITY_TLS_OPTIONAL ||
mConnectionSecurity == CONNECTION_SECURITY_SSL_OPTIONAL) {
this.mUrl = "https://" + mHost;
this.mUrl = "https://" + mHost + ":" + mUri.getPort();
} else {
this.mUrl = "http://" + mHost;
this.mUrl = "http://" + mHost + ":" + mUri.getPort();
}
if (mUri.getUserInfo() != null) {
@ -448,7 +433,7 @@ public class WebDavStore extends Store {
ArrayList<BasicNameValuePair> pairs = new ArrayList();
pairs.add(new BasicNameValuePair("username", username));
pairs.add(new BasicNameValuePair("password", password));
pairs.add(new BasicNameValuePair("destination", finalUrl + "/Exchange/"));
pairs.add(new BasicNameValuePair("destination", finalUrl + "/exchange/" +username+"/"));
pairs.add(new BasicNameValuePair("flags", "0"));
pairs.add(new BasicNameValuePair("SubmitCreds", "Log+On"));
pairs.add(new BasicNameValuePair("forcedownlevel", "0"));
@ -466,7 +451,7 @@ public class WebDavStore extends Store {
/** Verify success */
if (status_code < 500 &&
status_code > 400) {
status_code >= 400) {
String errorText = "";
String requestText = "";
if (entity != null) {
@ -483,6 +468,7 @@ public class WebDavStore extends Store {
while ((tempText = reader.readLine()) != null) {
requestText += tempText;
}
requestText = requestText.replaceAll("password=.*?&", "password=(omitted)&");
throw new MessagingException("Error during authentication: "+
response.getStatusLine().toString()+ "\n\nRequest: "+
requestText + "\n\nResponse: " +
@ -538,25 +524,25 @@ public class WebDavStore extends Store {
}
public DefaultHttpClient getTrustedHttpClient() throws KeyManagementException, NoSuchAlgorithmException{
DefaultHttpClient httpclient = new DefaultHttpClient();
/*
SchemeRegistry reg = httpclient.getConnectionManager().getSchemeRegistry();
reg.unregister("https");
Scheme s = new Scheme("https",new TrustedSocketFactory(mHost,mSecure),443);
reg.register(s);
*/
/*
//Add credentials for NTLM/Digest/Basic Auth
Credentials creds = new UsernamePasswordCredentials(mUsername, mPassword);
CredentialsProvider credsProvider = httpclient.getCredentialsProvider();
// setting AuthScope for 80 and 443, in case we end up getting redirected
// from 80 to 443.
credsProvider.setCredentials(new AuthScope(mHost, 80, AuthScope.ANY_REALM), creds);
credsProvider.setCredentials(new AuthScope(mHost, 443, AuthScope.ANY_REALM), creds);
credsProvider.setCredentials(new AuthScope(mHost, mUri.getPort(), AuthScope.ANY_REALM), creds);
httpclient.setCredentialsProvider(credsProvider);
*/
return httpclient;
if (mHttpClient == null) {
mHttpClient = new DefaultHttpClient();
SchemeRegistry reg = mHttpClient.getConnectionManager().getSchemeRegistry();
Scheme s = new Scheme("https",new TrustedSocketFactory(mHost,mSecure),443);
reg.register(s);
//Add credentials for NTLM/Digest/Basic Auth
Credentials creds = new UsernamePasswordCredentials(mUsername, mPassword);
CredentialsProvider credsProvider = mHttpClient.getCredentialsProvider();
// setting AuthScope for 80 and 443, in case we end up getting redirected
// from 80 to 443.
credsProvider.setCredentials(new AuthScope(mHost, 80, AuthScope.ANY_REALM), creds);
credsProvider.setCredentials(new AuthScope(mHost, 443, AuthScope.ANY_REALM), creds);
credsProvider.setCredentials(new AuthScope(mHost, mUri.getPort(), AuthScope.ANY_REALM), creds);
mHttpClient.setCredentialsProvider(credsProvider);
}
return mHttpClient;
}
/**
@ -622,13 +608,29 @@ public class WebDavStore extends Store {
response = httpclient.execute(httpmethod);
statusCode = response.getStatusLine().getStatusCode();
entity = response.getEntity();
if (statusCode < 500 &&
statusCode >= 400) {
String errorText = "";
if (entity != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()), 8192);
String tempText = "";
while ((tempText = reader.readLine()) != null) {
errorText += tempText;
}
}
throw new IOException("Error during authentication: "+
response.getStatusLine().toString()+ "\n\nRequest: "+
messageBody + "\n\nResponse: " +
errorText);
}
if (statusCode < 200 ||
statusCode > 300) {
throw new IOException("Error processing request, returned HTTP Response Code was " + statusCode);
}
entity = response.getEntity();
if (entity != null &&
needsParsing) {
try {
@ -1053,7 +1055,7 @@ public class WebDavStore extends Store {
if (statusCode < 200 ||
statusCode > 300) {
throw new IOException("Status Code in invalid range");
throw new IOException("Status Code in invalid range, URL: "+wdMessage.getUrl());
}
entity = response.getEntity();
@ -1091,7 +1093,7 @@ public class WebDavStore extends Store {
} catch (URISyntaxException use) {
Log.e(Email.LOG_TAG, "URISyntaxException caught " + use);
} catch (IOException ioe) {
Log.e(Email.LOG_TAG, "Non-success response code loading message, response code was " + statusCode);
Log.e(Email.LOG_TAG, "Non-success response code loading message, response code was: " + statusCode + " Error: "+ioe.getMessage());
}
if (listener != null) {
@ -1362,6 +1364,18 @@ public class WebDavStore extends Store {
}
public void setUrl(String url) {
//TODO: bleh. This is an ugly hack, but does prevent a crash if the url is relative
//FIXME: so fix, or better yet:
//XXX: prevent URLs from getting to us that are broken.
if (! (url.toLowerCase().contains(WebDavStore.this.mUrl.toLowerCase()+this.mFolder.toString().toLowerCase()))) {
if (!(url.startsWith("/"))){
url = "/" + url;
}
url = WebDavStore.this.mUrl + this.mFolder+url;
}
if (!(url.toLowerCase().contains(WebDavStore.this.mUrl.toLowerCase()))) {
url = WebDavStore.this.mUrl + url;
}
String[] urlParts = url.split("/");
int length = urlParts.length;
String end = urlParts[length - 1];

View File

@ -9,16 +9,17 @@ import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.params.HttpParams;
import com.android.email.mail.store.TrustManagerFactory;
public class TrustedSocketFactory implements SocketFactory {
public class TrustedSocketFactory implements LayeredSocketFactory {
private SSLSocketFactory mSocketFactory;
private org.apache.http.conn.ssl.SSLSocketFactory mSchemeSocketFactory;
@ -46,5 +47,19 @@ public class TrustedSocketFactory implements SocketFactory {
public boolean isSecure(Socket sock) throws IllegalArgumentException {
return mSchemeSocketFactory.isSecure(sock);
}
}
public Socket createSocket(
final Socket socket,
final String host,
final int port,
final boolean autoClose
) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) mSocketFactory.createSocket(
socket,
host,
port,
autoClose
);
//hostnameVerifier.verify(host, sslSocket);
// verifyHostName() didn't blowup - good!
return sslSocket;
}}