### Eclipse Workspace Patch 1.0
#P wagon
Index: wagon-provider-api/src/main/java/org/apache/maven/wagon/AbstractWagon.java
===================================================================
--- wagon-provider-api/src/main/java/org/apache/maven/wagon/AbstractWagon.java (revision 1053317)
+++ wagon-provider-api/src/main/java/org/apache/maven/wagon/AbstractWagon.java (working copy)
@@ -27,6 +27,12 @@
import java.io.OutputStream;
import java.util.List;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.authorization.AuthorizationException;
@@ -195,6 +201,12 @@
authenticationInfo.setPassword( repository.getPassword() );
}
}
+ // If there's no user/pass in the URL, see if there's a CallbackHandler
+ // specified and call out to it to get the username and password.
+ else
+ {
+ setUsernameAndPasswordUsingCallbackHandler( authenticationInfo );
+ }
}
// TODO: Do these needs to be fields, or are they only used in openConnection()?
@@ -208,7 +220,86 @@
fireSessionOpened();
}
-
+
+ /**
+ * Attempts to take the callbackHandlerClass name, create an instance of it and interrogate it for a
+ * username and password. If successful, adds the username and password details into authenticationInfo.
+ * If unsuccessful, fails relatively quietly; logging the error but not throwing an Exception.
+ *
+ * @param authenticationInfo username and password are updated if this method is successful
+ */
+ protected void setUsernameAndPasswordUsingCallbackHandler(AuthenticationInfo authenticationInfo)
+ {
+ assert authenticationInfo != null;
+
+ if(authenticationInfo.getCallbackHandlerClass() == null) {
+ return;
+ }
+
+ Class callbackHandlerClassObject;
+ try
+ {
+ callbackHandlerClassObject = Class.forName(authenticationInfo.getCallbackHandlerClass());
+ } catch (ClassNotFoundException e) {
+ //log the failure to find the CallbackHandler class
+ //Could throw a ConnectionException but that would stop
+ //the successful download of an artifact if no authentication
+ //is actually required.
+ return;
+ }
+
+ if(!CallbackHandler.class.isAssignableFrom(callbackHandlerClassObject))
+ {
+ //log the fact that the specified CallbackHandler class
+ //is not assignable to the CallbackHandler interface
+ return;
+ }
+
+ CallbackHandler callbackHandler;
+ try {
+ callbackHandler = (CallbackHandler)callbackHandlerClassObject.newInstance();
+ }
+ catch (InstantiationException e)
+ {
+ //Log the fact that the CallbackHandler class does not have a
+ //public default constructor
+ return;
+ }
+ catch (IllegalAccessException e)
+ {
+ //Log the fact that the CallbackHandler class is hidden
+ return;
+ }
+
+ //A SingleSignOn solution will not display these text prompts.
+ NameCallback usernameCallback = new NameCallback("SingleSignOn username");
+ PasswordCallback passwordCallback = new PasswordCallback("SingleSignOn password", false);
+
+ Callback[] callbacks = new Callback[] {
+ usernameCallback,
+ passwordCallback
+ };
+
+ try
+ {
+ callbackHandler.handle(callbacks);
+ }
+ catch (IOException e)
+ {
+ //log
+ return;
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ //log
+ return;
+ }
+
+ authenticationInfo.setUserName(usernameCallback.getName());
+ authenticationInfo.setPassword(new String(passwordCallback.getPassword()));
+
+ }
+
protected abstract void openConnectionInternal()
throws ConnectionException, AuthenticationException;
Index: wagon-provider-api/src/main/java/org/apache/maven/wagon/authentication/AuthenticationInfo.java
===================================================================
--- wagon-provider-api/src/main/java/org/apache/maven/wagon/authentication/AuthenticationInfo.java (revision 1053317)
+++ wagon-provider-api/src/main/java/org/apache/maven/wagon/authentication/AuthenticationInfo.java (working copy)
@@ -51,6 +51,8 @@
* The absolute path to private key file
*/
private String privateKey;
+
+ private String callbackHandlerClass;
/**
* Get the passphrase of the private key file. The passphrase is used only
@@ -133,4 +135,14 @@
{
this.userName = userName;
}
+
+ public String getCallbackHandlerClass()
+ {
+ return callbackHandlerClass;
+ }
+
+ public void setCallbackHandlerClass(String callbackHandlerClass)
+ {
+ this.callbackHandlerClass = callbackHandlerClass;
+ }
}
Index: wagon-provider-api/src/test/java/org/apache/maven/wagon/AbstractWagonTest.java
===================================================================
--- wagon-provider-api/src/test/java/org/apache/maven/wagon/AbstractWagonTest.java (revision 1053317)
+++ wagon-provider-api/src/test/java/org/apache/maven/wagon/AbstractWagonTest.java (working copy)
@@ -25,6 +25,12 @@
import java.io.InputStream;
import java.io.OutputStream;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
import junit.framework.TestCase;
import org.apache.maven.wagon.authentication.AuthenticationException;
@@ -601,4 +607,38 @@
return baos.toByteArray();
}
}
+
+ static class CBHandler implements CallbackHandler {
+ public static final String TESTUSER = "testuser";
+ public static final String TESTPASSWORD = "testpassword";
+
+ public void handle(javax.security.auth.callback.Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for(int i = 0; i < callbacks.length; i++) { //source level is 1.5 so we have to use old style loops
+ Callback callback = callbacks[i];
+ if(callback instanceof NameCallback) {
+ ((NameCallback)callback).setName(TESTUSER);
+ } else if(callback instanceof PasswordCallback) {
+ ((PasswordCallback)callback).setPassword(TESTPASSWORD.toCharArray());
+ }
+ }
+ };
+ }
+
+ public void testSingleSignOnWithCallbackHandler() {
+ AbstractWagon wagon = new TestWagon();
+ AuthenticationInfo authenticationInfo = new AuthenticationInfo();
+
+ //No exception gets thrown when passing in no CallbackHandlerClass
+ wagon.setUsernameAndPasswordUsingCallbackHandler(authenticationInfo);
+
+ //No exception gets thrown when a non-existent CallbackHandlerClass gets used
+ authenticationInfo.setCallbackHandlerClass("com.example.DoesNotExist");
+ wagon.setUsernameAndPasswordUsingCallbackHandler(authenticationInfo);
+
+ //Test a valid scenario
+ authenticationInfo.setCallbackHandlerClass(CBHandler.class.getName());
+ wagon.setUsernameAndPasswordUsingCallbackHandler(authenticationInfo);
+ assertEquals(CBHandler.TESTUSER, authenticationInfo.getUserName());
+ assertEquals(CBHandler.TESTPASSWORD, authenticationInfo.getPassword());
+ }
}
#P maven-3
Index: pom.xml
===================================================================
--- pom.xml (revision 1053317)
+++ pom.xml (working copy)
@@ -45,12 +45,12 @@
1.14
2.0.4
1.4.3.1
- 1.0-beta-7
+ 1.0-beta-8-SNAPSHOT
1.3
1.4
1.4
1.3
- 1.8
+ 1.9-SNAPSHOT
true
Index: maven-core/src/main/java/org/apache/maven/RepositoryUtils.java
===================================================================
--- maven-core/src/main/java/org/apache/maven/RepositoryUtils.java (revision 1053317)
+++ maven-core/src/main/java/org/apache/maven/RepositoryUtils.java (working copy)
@@ -222,7 +222,7 @@
if ( auth != null )
{
result =
- new Authentication( auth.getUsername(), auth.getPassword(), auth.getPrivateKey(), auth.getPassphrase() );
+ new Authentication( auth.getUsername(), auth.getPassword(), auth.getPrivateKey(), auth.getPassphrase(), auth.getCallbackHandlerClass() );
}
return result;
}
Index: maven-core/src/main/java/org/apache/maven/DefaultMaven.java
===================================================================
--- maven-core/src/main/java/org/apache/maven/DefaultMaven.java (revision 1053317)
+++ maven-core/src/main/java/org/apache/maven/DefaultMaven.java (working copy)
@@ -398,7 +398,7 @@
{
Authentication auth =
new Authentication( server.getUsername(), server.getPassword(), server.getPrivateKey(),
- server.getPassphrase() );
+ server.getPassphrase(), server.getCallbackHandlerClass() );
authSelector.add( server.getId(), auth );
if ( server.getConfiguration() != null )
Index: maven-settings/src/main/mdo/settings.mdo
===================================================================
--- maven-settings/src/main/mdo/settings.mdo (revision 1053317)
+++ maven-settings/src/main/mdo/settings.mdo (working copy)
@@ -560,6 +560,17 @@
String
+ callbackHandlerClass
+ 1.0.0+
+
+
+
+ String
+
+
privateKey
1.0.0+
Index: maven-artifact/src/main/java/org/apache/maven/artifact/repository/Authentication.java
===================================================================
--- maven-artifact/src/main/java/org/apache/maven/artifact/repository/Authentication.java (revision 1053317)
+++ maven-artifact/src/main/java/org/apache/maven/artifact/repository/Authentication.java (working copy)
@@ -25,6 +25,8 @@
private String privateKey;
private String passphrase;
+
+ private String callbackHandlerClass;
public Authentication( String userName, String password )
{
@@ -123,4 +125,12 @@
this.privateKey = privateKey;
}
+ public String getCallbackHandlerClass() {
+ return callbackHandlerClass;
+ }
+
+ public void setCallbackHandlerClass(String callbackHandlerClass) {
+ this.callbackHandlerClass = callbackHandlerClass;
+ }
+
}