Index: plexus-components/plexus-formica/src/main/java/org/codehaus/plexus/formica/validation/UrlSourceValidator.java =================================================================== --- plexus-components/plexus-formica/src/main/java/org/codehaus/plexus/formica/validation/UrlSourceValidator.java (revision 2413) +++ plexus-components/plexus-formica/src/main/java/org/codehaus/plexus/formica/validation/UrlSourceValidator.java (working copy) @@ -10,10 +10,17 @@ import org.codehaus.plexus.formica.FormicaException; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; +import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.URL; import java.net.MalformedURLException; -import java.io.InputStream; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + + /** * @plexus.component * role-hint="url-source" @@ -28,6 +35,7 @@ public class UrlSourceValidator extends AbstractValidator { + public boolean validate( String urlString ) { try @@ -38,13 +46,16 @@ // want to make sure the URL corresponds to an existing resource. // ---------------------------------------------------------------------- - //TODO: we need to support authentication (CONTINUUM-258) + // if it is a https connection then we have a bit more work to do + if ( urlString != null && urlString.startsWith("https") ) { + return validateSecureURL( urlString ); + } else { + URL url = new URL( urlString ); - URL url = new URL( urlString ); + InputStream is = url.openStream(); - InputStream is = url.openStream(); - - is.close(); + is.close(); + } } catch ( Exception e ) { @@ -53,4 +64,90 @@ return true; } + + /* this bit attempts to ignore certificates that might need to be accepted and also tries to + * conform to the format https://:@host + * + * adapted from code snippets from http://javaalmanac.com/egs/javax.net.ssl/TrustAll.html * + */ + public boolean validateSecureURL( String urlString ) { + + try { + + // Create a trust manager that does not validate certificate + // chains + TrustManager[] trustAllCerts = new TrustManager[] { + new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + + // Install the all-trusting trust manager + + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + + String username = scrapeUsername( urlString ); + String password = scrapePassword( urlString ); + String authString = username + ":" + password; + String cleanUrl = scrapeUrl( urlString ); + + URL url = new URL( cleanUrl ); + + HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); + + urlc.setDoInput( true ); + urlc.setUseCaches( false ); + + urlc.setRequestProperty( "Content-Type", "application/octet-stream" ); + + if (username != null && password != null) { + urlc.setRequestProperty( "Authorization", "Basic " + new sun.misc.BASE64Encoder().encode( authString.getBytes() ) ); + } + + InputStream is = urlc.getInputStream(); + is.close(); + + } catch (Exception e) { + return false; + } + return true; + } + + /* + * return the username from https://:@ + */ + private String scrapeUsername (String url) { + String t = url.substring(8, url.length()); + return t.substring(0, t.indexOf(":")); + } + + /* + * return to password from https://:@ + */ + private String scrapePassword (String url) { + String t = url.substring(8, url.length()); + return t.substring(t.indexOf(":") + 1, t.indexOf("@")); + } + + /* + * return the url from https://:@ + */ + private String scrapeUrl (String url) { + if (url.indexOf("@") != -1) { + return "https://" + url.substring(url.indexOf("@") + 1, url.length()); + } else { + return url; + } + } + }