diff options
42 files changed, 1275 insertions, 342 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOAuthenticator.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOAuthenticator.java index 30490a2c7e..11dd65f4aa 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOAuthenticator.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOAuthenticator.java @@ -16,10 +16,12 @@ import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; /** * The front-end of the CDO challenge/response authentication. - * + * * @author Eike Stepper * @since 2.0 + * @deprecated As of 4.2 use {@link IPasswordCredentialsProvider} directly */ +@Deprecated public interface CDOAuthenticator { public String getEncryptionAlgorithmName(); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/CDOAuthenticationResult.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/CDOAuthenticationResult.java index 02fb08a08b..864a17350f 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/CDOAuthenticationResult.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/CDOAuthenticationResult.java @@ -18,10 +18,12 @@ import java.io.Serializable; /** * The result of an authentication operation. Carries a userID and a crypted token. - * + * * @author Eike Stepper * @since 4.0 + * @deprecated As of 4.2 */ +@Deprecated public final class CDOAuthenticationResult implements Serializable { private static final long serialVersionUID = 1L; diff --git a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml index 7475eefacd..f399432080 100644 --- a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml @@ -28,11 +28,7 @@ --> <!-- Example http://bugs.eclipse.org/302775 - <userManager type="file" description="_database/repo1.users"/> - --> - - <!-- Example http://bugs.eclipse.org/34583 - <userManager type="TestRepository" description="repo1"/> + <authenticator type="file" description="_database/repo1.users"/> --> <!-- Example http://bugs.eclipse.org/345431 diff --git a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml index 7475eefacd..f399432080 100644 --- a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml @@ -28,11 +28,7 @@ --> <!-- Example http://bugs.eclipse.org/302775 - <userManager type="file" description="_database/repo1.users"/> - --> - - <!-- Example http://bugs.eclipse.org/34583 - <userManager type="TestRepository" description="repo1"/> + <authenticator type="file" description="_database/repo1.users"/> --> <!-- Example http://bugs.eclipse.org/345431 diff --git a/plugins/org.eclipse.emf.cdo.examples.server/src/org/eclipse/emf/cdo/examples/server/DemoConfiguration.java b/plugins/org.eclipse.emf.cdo.examples.server/src/org/eclipse/emf/cdo/examples/server/DemoConfiguration.java index a8b9a202a4..d406c87b1f 100644 --- a/plugins/org.eclipse.emf.cdo.examples.server/src/org/eclipse/emf/cdo/examples/server/DemoConfiguration.java +++ b/plugins/org.eclipse.emf.cdo.examples.server/src/org/eclipse/emf/cdo/examples/server/DemoConfiguration.java @@ -32,7 +32,7 @@ import org.eclipse.net4j.util.event.IListener; import org.eclipse.net4j.util.io.IOUtil; import org.eclipse.net4j.util.lifecycle.Lifecycle; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; -import org.eclipse.net4j.util.security.IUserManager; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.net4j.util.security.UserManager; import org.h2.jdbcx.JdbcDataSource; @@ -149,8 +149,8 @@ public class DemoConfiguration extends Lifecycle if (userIDs != null) { - IUserManager userManager = createUserManager(); - sessionManager.setUserManager(userManager); + IAuthenticator authenticator = createAuthenticator(); + sessionManager.setAuthenticator(authenticator); } CDOServerUtil.addRepository(IPluginContainer.INSTANCE, repository); @@ -235,7 +235,7 @@ public class DemoConfiguration extends Lifecycle return sessionManager; } - protected IUserManager createUserManager() + protected IAuthenticator createAuthenticator() { userManager = new DemoUserManager(); for (int i = 0; i < userIDs.length; i++) diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/CDONet4jSessionImpl.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/CDONet4jSessionImpl.java index 127a0aad46..45fbe8b67c 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/CDONet4jSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/CDONet4jSessionImpl.java @@ -36,6 +36,7 @@ import org.eclipse.emf.internal.cdo.session.DelegatingSessionProtocol; import org.eclipse.net4j.connector.IConnector; import org.eclipse.net4j.signal.ISignalProtocol; +import org.eclipse.net4j.signal.RemoteException; import org.eclipse.net4j.signal.SignalProtocol; import org.eclipse.net4j.util.io.IStreamWrapper; @@ -223,21 +224,33 @@ public class CDONet4jSessionImpl extends CDOSessionImpl implements org.eclipse.e setSessionProtocol(protocol); hookSessionProtocol(); - // TODO (CD) The next call is on the CDOClientProtocol; shouldn't it be on the DelegatingSessionProtocol instead? - OpenSessionResult result = protocol.openSession(repositoryName, getUserID(), options().isPassiveUpdateEnabled(), - options().getPassiveUpdateMode(), options().getLockNotificationMode()); - - if (result == null) + try { - // Skip to response because the user has canceled the authentication - return null; + // TODO (CD) The next call is on the CDOClientProtocol; shouldn't it be on the DelegatingSessionProtocol instead? + OpenSessionResult result = protocol.openSession(repositoryName, getUserID(), options().isPassiveUpdateEnabled(), + options().getPassiveUpdateMode(), options().getLockNotificationMode()); + + if (result == null) + { + // Skip to response because the user has canceled the authentication + return null; + } + + setSessionID(result.getSessionID()); + setUserID(result.getUserID()); + setLastUpdateTime(result.getLastUpdateTime()); + setRepositoryInfo(new RepositoryInfo(this, repositoryName, result)); + return result; } + catch (RemoteException ex) + { + if (ex.getCause() instanceof SecurityException) + { + throw (SecurityException)ex.getCause(); + } - setSessionID(result.getSessionID()); - setUserID(result.getUserID()); - setLastUpdateTime(result.getLastUpdateTime()); - setRepositoryInfo(new RepositoryInfo(this, repositoryName, result)); - return result; + throw ex; + } } @Override diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/Net4jSessionFactory.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/Net4jSessionFactory.java index f790c147af..f78ba23c5c 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/Net4jSessionFactory.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/Net4jSessionFactory.java @@ -51,7 +51,7 @@ public class Net4jSessionFactory extends CDOSessionFactory CDONet4jSessionConfiguration configuration = CDONet4jUtil.createNet4jSessionConfiguration(); configuration.setRepositoryName(repositoryName); configuration.setUserID(userID); - configuration.getAuthenticator().setCredentialsProvider(getCredentialsProvider()); + configuration.setCredentialsProvider(getCredentialsProvider()); // The session will be activated by the container configuration.setActivateOnOpen(false); diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/AuthenticationIndication.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/AuthenticationIndication.java index 361377c551..5e379e66a3 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/AuthenticationIndication.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/AuthenticationIndication.java @@ -10,25 +10,32 @@ */ package org.eclipse.emf.cdo.internal.net4j.protocol; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; +import org.eclipse.emf.cdo.internal.net4j.bundle.OM; import org.eclipse.net4j.signal.IndicationWithMonitoring; import org.eclipse.net4j.signal.SignalProtocol; +import org.eclipse.net4j.util.StringUtil; import org.eclipse.net4j.util.io.ExtendedDataInputStream; import org.eclipse.net4j.util.io.ExtendedDataOutputStream; import org.eclipse.net4j.util.om.monitor.OMMonitor; import org.eclipse.net4j.util.om.monitor.OMMonitor.Async; +import org.eclipse.net4j.util.security.DiffieHellman; +import org.eclipse.net4j.util.security.DiffieHellman.Client.Response; +import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge; +import org.eclipse.net4j.util.security.IPasswordCredentials; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.emf.spi.cdo.InternalCDOSession; +import java.io.ByteArrayOutputStream; + /** * @author Eike Stepper */ public class AuthenticationIndication extends IndicationWithMonitoring { - private byte[] randomToken; + private Challenge challenge; public AuthenticationIndication(SignalProtocol<?> protocol) { @@ -49,7 +56,7 @@ public class AuthenticationIndication extends IndicationWithMonitoring @Override protected void indicating(ExtendedDataInputStream in, OMMonitor monitor) throws Exception { - randomToken = in.readByteArray(); + challenge = new Challenge(in); } @Override @@ -60,38 +67,74 @@ public class AuthenticationIndication extends IndicationWithMonitoring try { - CDOAuthenticator authenticator = getSession().getAuthenticator(); - if (authenticator == null) + IPasswordCredentialsProvider credentialsProvider = getSession().getCredentialsProvider(); + if (credentialsProvider == null) { - throw new IllegalStateException("No authenticator configured"); //$NON-NLS-1$ + throw new IllegalStateException("No credentials provider configured"); //$NON-NLS-1$ } - CDOAuthenticationResult result = authenticator.authenticate(randomToken); - if (result == null) + IPasswordCredentials credentials = credentialsProvider.getCredentials(); + if (credentials == null) { - out.writeBoolean(false); - return; + throw new IllegalStateException("No credentials provided"); //$NON-NLS-1$ } - String userID = result.getUserID(); - if (userID == null) + String userID = credentials.getUserID(); + if (StringUtil.isEmpty(userID)) { - throw new SecurityException("No user ID"); //$NON-NLS-1$ + throw new IllegalStateException("No userID provided"); //$NON-NLS-1$ } - byte[] cryptedToken = result.getCryptedToken(); - if (cryptedToken == null) + String password = new String(credentials.getPassword()); + if (StringUtil.isEmpty(userID)) { - throw new SecurityException("No crypted token"); //$NON-NLS-1$ + throw new IllegalStateException("No password provided"); //$NON-NLS-1$ } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ExtendedDataOutputStream stream = new ExtendedDataOutputStream(baos); + stream.writeString(userID); + stream.writeString(password); + stream.flush(); + byte[] clearText = baos.toByteArray(); + + DiffieHellman.Client client = new DiffieHellman.Client(); + Response response = client.handleChallenge(challenge, clearText); out.writeBoolean(true); - result.write(out); + response.write(out); + + // CDOAuthenticator authenticator = getSession().getAuthenticator(); + // if (authenticator == null) + // { + // throw new IllegalStateException("No authenticator configured"); //$NON-NLS-1$ + // } + // + // CDOAuthenticationResult result = authenticator.authenticate(challenge); + // if (result == null) + // { + // out.writeBoolean(false); + // return; + // } + // + // String userID = result.getUserID(); + // if (userID == null) + // { + // throw new SecurityException("No user ID"); //$NON-NLS-1$ + // } + // + // byte[] cryptedToken = result.getCryptedToken(); + // if (cryptedToken == null) + // { + // throw new SecurityException("No crypted token"); //$NON-NLS-1$ + // } + // + // out.writeBoolean(true); + // result.write(out); } - catch (Exception ex) + catch (Throwable ex) { out.writeBoolean(false); - throw ex; + OM.LOG.error(ex); } finally { diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/net4j/CDONet4jViewProvider.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/net4j/CDONet4jViewProvider.java index 669d80f74c..f9db6987e8 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/net4j/CDONet4jViewProvider.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/net4j/CDONet4jViewProvider.java @@ -195,7 +195,7 @@ public abstract class CDONet4jViewProvider extends AbstractCDOViewProvider } } - configuration.getAuthenticator().setCredentialsProvider(credentialsProvider); + configuration.setCredentialsProvider(credentialsProvider); return configuration; } diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/AuthenticationRequest.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/AuthenticationRequest.java index 163350a3a9..d5867e2ff7 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/AuthenticationRequest.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/AuthenticationRequest.java @@ -12,42 +12,42 @@ package org.eclipse.emf.cdo.server.internal.net4j.protocol; import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.common.util.NotAuthenticatedException; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; import org.eclipse.net4j.signal.RemoteException; import org.eclipse.net4j.signal.RequestWithMonitoring; import org.eclipse.net4j.util.io.ExtendedDataInputStream; import org.eclipse.net4j.util.io.ExtendedDataOutputStream; import org.eclipse.net4j.util.om.monitor.OMMonitor; +import org.eclipse.net4j.util.security.DiffieHellman.Client.Response; +import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge; /** * @author Eike Stepper */ -public class AuthenticationRequest extends RequestWithMonitoring<CDOAuthenticationResult> +public class AuthenticationRequest extends RequestWithMonitoring<Response> { - private byte[] randomToken; + private Challenge challenge; - public AuthenticationRequest(CDOServerProtocol protocol, byte[] randomToken) + public AuthenticationRequest(CDOServerProtocol protocol, Challenge challenge) { super(protocol, CDOProtocolConstants.SIGNAL_AUTHENTICATION); - this.randomToken = randomToken; + this.challenge = challenge; } @Override protected void requesting(ExtendedDataOutputStream out, OMMonitor monitor) throws Exception { - out.writeByteArray(randomToken); + challenge.write(out); } @Override - protected CDOAuthenticationResult confirming(ExtendedDataInputStream in, OMMonitor monitor) throws Exception + protected Response confirming(ExtendedDataInputStream in, OMMonitor monitor) throws Exception { try { - boolean authenticated = in.readBoolean(); - if (authenticated) + if (in.readBoolean()) { - return new CDOAuthenticationResult(in); + return new Response(in); } } catch (RemoteException ex) diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java index dcc2ffd447..b2414e325f 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java @@ -22,7 +22,6 @@ import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.server.IRepositoryProvider; import org.eclipse.emf.cdo.server.internal.net4j.bundle.OM; import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; import org.eclipse.emf.cdo.spi.server.ISessionProtocol; import org.eclipse.emf.cdo.spi.server.InternalSession; @@ -32,6 +31,8 @@ import org.eclipse.net4j.signal.SignalReactor; import org.eclipse.net4j.util.io.StringCompressor; import org.eclipse.net4j.util.io.StringIO; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; +import org.eclipse.net4j.util.security.DiffieHellman.Client.Response; +import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge; /** * @author Eike Stepper @@ -83,9 +84,16 @@ public class CDOServerProtocol extends SignalProtocol<InternalSession> implement this.negotiationTimeout = negotiationTimeout; } - public CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) throws Exception + @Deprecated + public org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) + throws Exception + { + throw new UnsupportedOperationException(); + } + + public Response sendAuthenticationChallenge(Challenge challenge) throws Exception { - return new AuthenticationRequest(this, randomToken).send(negotiationTimeout); + return new AuthenticationRequest(this, challenge).send(negotiationTimeout); } public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType) diff --git a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml index e2e791cb30..9b730ec346 100644 --- a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml @@ -28,11 +28,7 @@ --> <!-- Example http://bugs.eclipse.org/302775 - <userManager type="file" description="_database/repo1.users"/> - --> - - <!-- Example http://bugs.eclipse.org/34583 - <userManager type="TestRepository" description="repo1"/> + <authenticator type="file" description="_database/repo1.users"/> --> <!-- Example http://bugs.eclipse.org/345431 diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java index 8dd57ce4b8..a86ee4d351 100644 --- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java +++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java @@ -56,13 +56,12 @@ import org.eclipse.net4j.util.lifecycle.Lifecycle; import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.monitor.OMMonitor; -import org.eclipse.net4j.util.security.IUserManager; -import org.eclipse.net4j.util.security.SecurityUtil; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.util.EcoreUtil; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -77,20 +76,17 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage @Override protected void onActivated(ILifecycle lifecycle) { - if (isActive()) - { - init(); - } + init(); } @Override protected void onDeactivated(ILifecycle lifecycle) { - deactivate(); + SecurityManager.this.deactivate(); } }; - private final IUserManager userManager = new UserManager(); + private final IAuthenticator authenticator = new Authenticator(); private final IPermissionManager permissionManager = new PermissionManager(); @@ -242,7 +238,11 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage { public void execute(Realm realm) { + UserPassword userPassword = SecurityFactory.eINSTANCE.createUserPassword(); + userPassword.setEncrypted(new String(password)); + result[0] = realm.addUser(id); + result[0].setPassword(userPassword); } }); @@ -373,14 +373,22 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage protected void init() { + if (realm != null) + { + // Already initialized + return; + } + if (repository == null) { + // Cannot initialize return; } repository.addListener(repositoryListener); if (!LifecycleUtil.isActive(repository)) { + // Cannot initialize now return; } @@ -422,7 +430,7 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage } InternalSessionManager sessionManager = repository.getSessionManager(); - sessionManager.setUserManager(userManager); + sessionManager.setAuthenticator(authenticator); sessionManager.setPermissionManager(permissionManager); repository.addHandler(writeAccessHandler); } @@ -561,61 +569,17 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage /** * @author Eike Stepper */ - private final class UserManager implements IUserManager + private final class Authenticator implements IAuthenticator { - public void addUser(final String userID, final char[] password) - { - modify(new RealmOperation() - { - public void execute(Realm realm) - { - UserPassword userPassword = SecurityFactory.eINSTANCE.createUserPassword(); - userPassword.setEncrypted(new String(password)); - - User user = SecurityFactory.eINSTANCE.createUser(); - user.setId(userID); - user.setPassword(userPassword); - - realm.getItems().add(user); - } - }); - } - - public void removeUser(final String userID) - { - modify(new RealmOperation() - { - public void execute(Realm realm) - { - User user = getUser(userID); - EcoreUtil.remove(user); - } - }); - } - - public byte[] encrypt(String userID, byte[] data, String algorithmName, byte[] salt, int count) - throws SecurityException + public void authenticate(String userID, char[] password) throws SecurityException { User user = getUser(userID); UserPassword userPassword = user.getPassword(); - String encrypted = userPassword == null ? null : userPassword.getEncrypted(); - char[] password = encrypted == null ? null : encrypted.toCharArray(); - if (password == null) - { - throw new SecurityException("No password: " + userID); - } - try - { - return SecurityUtil.encrypt(data, password, algorithmName, salt, count); - } - catch (RuntimeException ex) - { - throw ex; - } - catch (Exception ex) + String encrypted = userPassword.getEncrypted(); + if (!Arrays.equals(password, encrypted == null ? null : encrypted.toCharArray())) { - throw new SecurityException(ex); + throw new SecurityException("Access denied"); //$NON-NLS-1$ } } } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java index c9110b118f..0dc84e5bcc 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java @@ -22,7 +22,6 @@ import org.eclipse.emf.cdo.common.lob.CDOLobStore; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; @@ -58,6 +57,7 @@ import org.eclipse.net4j.util.lifecycle.LifecycleException; import org.eclipse.net4j.util.lifecycle.LifecycleState; import org.eclipse.net4j.util.ref.ReferenceType; import org.eclipse.net4j.util.ref.ReferenceValueMap; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.ecore.EObject; @@ -941,12 +941,24 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd throw new UnsupportedOperationException(); } - public CDOAuthenticator getAuthenticator() + @Deprecated + public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator() + { + throw new UnsupportedOperationException(); + } + + @Deprecated + public void setAuthenticator(org.eclipse.emf.cdo.common.protocol.CDOAuthenticator authenticator) + { + throw new UnsupportedOperationException(); + } + + public IPasswordCredentialsProvider getCredentialsProvider() { throw new UnsupportedOperationException(); } - public void setAuthenticator(CDOAuthenticator authenticator) + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider) { throw new UnsupportedOperationException(); } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java index 3c787f9800..03a1c2556c 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java @@ -23,25 +23,25 @@ import org.eclipse.emf.cdo.internal.server.bundle.OM; import org.eclipse.emf.cdo.server.IPermissionManager; import org.eclipse.emf.cdo.server.ISession; import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; import org.eclipse.emf.cdo.spi.server.ISessionProtocol; import org.eclipse.emf.cdo.spi.server.InternalRepository; import org.eclipse.emf.cdo.spi.server.InternalSession; import org.eclipse.emf.cdo.spi.server.InternalSessionManager; -import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; import org.eclipse.net4j.util.container.Container; +import org.eclipse.net4j.util.io.ExtendedDataInputStream; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.trace.ContextTracer; -import org.eclipse.net4j.util.security.IRandomizer; +import org.eclipse.net4j.util.security.DiffieHellman; +import org.eclipse.net4j.util.security.DiffieHellman.Client.Response; +import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.net4j.util.security.IUserManager; -import org.eclipse.net4j.util.security.NegotiationException; -import org.eclipse.net4j.util.security.Randomizer; -import org.eclipse.net4j.util.security.SecurityUtil; +import org.eclipse.net4j.util.security.UserManagerAuthenticator; +import java.io.ByteArrayInputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -52,26 +52,13 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class SessionManager extends Container<ISession> implements InternalSessionManager { - public static final int DEFAULT_TOKEN_LENGTH = 1024; - private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, SessionManager.class); private InternalRepository repository; - @ExcludeFromDump - private String encryptionAlgorithmName = SecurityUtil.PBE_WITH_MD5_AND_DES; - - @ExcludeFromDump - private byte[] encryptionSaltBytes = SecurityUtil.DEFAULT_SALT; - - @ExcludeFromDump - private int encryptionIterationCount = SecurityUtil.DEFAULT_ITERATION_COUNT; - - private int tokenLength = DEFAULT_TOKEN_LENGTH; + private DiffieHellman.Server authenticationServer; - private IRandomizer randomizer; - - private IUserManager userManager; + private IAuthenticator authenticator; private IPermissionManager permissionManager; @@ -103,69 +90,48 @@ public class SessionManager extends Container<ISession> implements InternalSessi this.repository = repository; } - public String getEncryptionAlgorithmName() - { - return encryptionAlgorithmName; - } - - public void setEncryptionAlgorithmName(String encryptionAlgorithmName) - { - checkInactive(); - this.encryptionAlgorithmName = encryptionAlgorithmName; - } - - public byte[] getEncryptionSaltBytes() - { - return encryptionSaltBytes; - } - - public void setEncryptionSaltBytes(byte[] encryptionSaltBytes) - { - checkInactive(); - this.encryptionSaltBytes = encryptionSaltBytes; - } - - public int getEncryptionIterationCount() + @Deprecated + public IUserManager getUserManager() { - return encryptionIterationCount; - } + if (authenticator instanceof UserManagerAuthenticator) + { + return ((UserManagerAuthenticator)authenticator).getUserManager(); + } - public void setEncryptionIterationCount(int encryptionIterationCount) - { - checkInactive(); - this.encryptionIterationCount = encryptionIterationCount; + return null; } - public int getTokenLength() + @Deprecated + public void setUserManager(IUserManager userManager) { - return tokenLength; - } + UserManagerAuthenticator userManagerAuthenticator = new UserManagerAuthenticator(); + userManagerAuthenticator.setUserManager(userManager); - public void setTokenLength(int tokenLength) - { - checkInactive(); - this.tokenLength = tokenLength; + setAuthenticator(userManagerAuthenticator); } - public IRandomizer getRandomizer() + public DiffieHellman.Server getAuthenticationServer() { - return randomizer; + return authenticationServer; } - public void setRandomizer(IRandomizer randomizer) + public void setAuthenticationServer(DiffieHellman.Server authenticationServer) { - checkInactive(); - this.randomizer = randomizer; + this.authenticationServer = authenticationServer; } - public IUserManager getUserManager() + public IAuthenticator getAuthenticator() { - return userManager; + return authenticator; } - public void setUserManager(IUserManager userManager) + public void setAuthenticator(IAuthenticator authenticator) { - this.userManager = userManager; + this.authenticator = authenticator; + if (isActive() && authenticator != null) + { + initAuthentication(); + } } public IPermissionManager getPermissionManager() @@ -422,30 +388,27 @@ public class SessionManager extends Container<ISession> implements InternalSessi return null; } - if (userManager == null) + if (authenticationServer == null || authenticator == null) { return null; } try { - byte[] randomToken = createRandomToken(); - CDOAuthenticationResult result = protocol.sendAuthenticationChallenge(randomToken); - if (result == null) + Challenge challenge = authenticationServer.getChallenge(); + Response response = protocol.sendAuthenticationChallenge(challenge); + if (response == null) { throw new NotAuthenticatedException(); } - String userID = result.getUserID(); + ByteArrayInputStream baos = new ByteArrayInputStream(authenticationServer.handleResponse(response)); + ExtendedDataInputStream stream = new ExtendedDataInputStream(baos); + String userID = stream.readString(); + char[] password = stream.readString().toCharArray(); - byte[] cryptedToken = encryptToken(userID, randomToken); - boolean success = Arrays.equals(result.getCryptedToken(), cryptedToken); - if (success) - { - return userID; - } - - throw new SecurityException("Access denied"); //$NON-NLS-1$ + authenticator.authenticate(userID, password); + return userID; } catch (SecurityException ex) { @@ -463,47 +426,36 @@ public class SessionManager extends Container<ISession> implements InternalSessi } } - protected byte[] createRandomToken() - { - byte[] token = new byte[tokenLength]; - randomizer.nextBytes(token); - return token; - } - - protected byte[] encryptToken(String userID, byte[] token) throws NegotiationException - { - try - { - return userManager.encrypt(userID, token, getEncryptionAlgorithmName(), getEncryptionSaltBytes(), - getEncryptionIterationCount()); - } - catch (Exception ex) - { - OM.LOG.error("Token encryption failed", ex); //$NON-NLS-1$ - return null; - } - } - @Override protected void doActivate() throws Exception { super.doActivate(); + initAuthentication(); + } - if (randomizer == null) + protected void initAuthentication() + { + if (authenticator != null) { - randomizer = new Randomizer(); - } + if (authenticationServer == null) + { + authenticationServer = new DiffieHellman.Server(); + } - LifecycleUtil.activate(randomizer); + LifecycleUtil.activate(authenticationServer); + LifecycleUtil.activate(authenticator); + } } @Override protected void doDeactivate() throws Exception { - InternalSession[] activeSessions = getSessions(); - for (int i = 0; i < activeSessions.length; i++) + LifecycleUtil.deactivate(authenticator); + LifecycleUtil.deactivate(authenticationServer); + + for (InternalSession session : getSessions()) { - LifecycleUtil.deactivate(activeSessions[i]); + LifecycleUtil.deactivate(session); } super.doDeactivate(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java index 53ccdaeadb..37a52973f5 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedServerSessionProtocol.java @@ -15,13 +15,14 @@ import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; import org.eclipse.emf.cdo.spi.server.ISessionProtocol; import org.eclipse.emf.cdo.spi.server.InternalRepository; import org.eclipse.emf.cdo.spi.server.InternalSession; import org.eclipse.net4j.util.lifecycle.Lifecycle; +import org.eclipse.net4j.util.security.DiffieHellman.Client.Response; +import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge; /** * @author Eike Stepper @@ -57,11 +58,18 @@ public class EmbeddedServerSessionProtocol extends Lifecycle implements ISession return session; } - public CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) throws Exception + @Deprecated + public org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) + throws Exception { return clientSessionProtocol.handleAuthenticationChallenge(randomToken); } + public Response sendAuthenticationChallenge(Challenge challenge) throws Exception + { + throw new UnsupportedOperationException(); + } + public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType) { EmbeddedClientSession clientSession = clientSessionProtocol.getSession(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java index b1e4bab6c6..3bc7979e85 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java @@ -11,10 +11,11 @@ package org.eclipse.emf.cdo.server; import org.eclipse.net4j.util.container.IContainer; +import org.eclipse.net4j.util.security.IAuthenticator; /** * Manages the user {@link ISession sessions} of a {@link IRepository repository}. - * + * * @author Eike Stepper * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. @@ -34,4 +35,14 @@ public interface ISessionManager extends IContainer<ISession> * @since 2.0 */ public ISession getSession(int sessionID); + + /** + * @since 4.2 + */ + public IAuthenticator getAuthenticator(); + + /** + * @since 4.2 + */ + public void setAuthenticator(IAuthenticator authenticator); } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java index 56ce4b85d4..34eee8014e 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/ISessionProtocol.java @@ -16,9 +16,11 @@ import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.protocol.CDOProtocol; import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; +import org.eclipse.net4j.util.security.DiffieHellman.Client.Response; +import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge; + /** * If the meaning of this type isn't clear, there really should be more of a description here... * @@ -31,8 +33,16 @@ public interface ISessionProtocol extends CDOProtocol { /** * @since 4.0 + * @deprecated As of 4.2 {@link #sendAuthenticationChallenge(Challenge)} is called. + */ + @Deprecated + public org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) + throws Exception; + + /** + * @since 4.2 */ - public CDOAuthenticationResult sendAuthenticationChallenge(byte[] randomToken) throws Exception; + public Response sendAuthenticationChallenge(Challenge challenge) throws Exception; public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType) throws Exception; diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java index 29af5aa91d..294bfb9c5c 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalSessionManager.java @@ -19,6 +19,8 @@ import org.eclipse.emf.cdo.server.ISessionManager; import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage; import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; +import org.eclipse.net4j.util.security.DiffieHellman; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.net4j.util.security.IUserManager; import java.util.List; @@ -39,12 +41,28 @@ public interface InternalSessionManager extends ISessionManager /** * @since 4.1 + * @deprecated As of 4.2 use {@link #getAuthenticator()} */ + @Deprecated public IUserManager getUserManager(); + /** + * @deprecated As of 4.2 use {@link #setAuthenticator(IAuthenticator)} + */ + @Deprecated public void setUserManager(IUserManager userManager); /** + * @since 4.2 + */ + public DiffieHellman.Server getAuthenticationServer(); + + /** + * @since 4.2 + */ + public void setAuthenticationServer(DiffieHellman.Server authenticationServer); + + /** * @since 4.1 */ public IPermissionManager getPermissionManager(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java index 293d48db52..b68cc86d6b 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryConfigurator.java @@ -24,7 +24,10 @@ import org.eclipse.net4j.util.StringUtil; import org.eclipse.net4j.util.container.IManagedContainer; import org.eclipse.net4j.util.om.OMPlatform; import org.eclipse.net4j.util.om.trace.ContextTracer; +import org.eclipse.net4j.util.security.AuthenticatorFactory; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.net4j.util.security.IUserManager; +import org.eclipse.net4j.util.security.UserManagerFactory; import org.eclipse.emf.ecore.EPackage; @@ -170,22 +173,8 @@ public class RepositoryConfigurator repository.setStore((InternalStore)store); repository.setProperties(properties); - Element userManagerConfig = getUserManagerConfig(repositoryConfig); - if (userManagerConfig != null) - { - IUserManager userManager = getUserManager(userManagerConfig); - if (userManager != null) - { - InternalSessionManager sessionManager = repository.getSessionManager(); - if (sessionManager == null) - { - sessionManager = new SessionManager(); - repository.setSessionManager(sessionManager); - } - - sessionManager.setUserManager(userManager); - } - } + setUserManager(repository, repositoryConfig); + setAuthenticator(repository, repositoryConfig); EPackage[] initialPackages = getInitialPackages(repositoryConfig); if (initialPackages.length != 0) @@ -223,7 +212,7 @@ public class RepositoryConfigurator protected IUserManager getUserManager(String type, String description) throws CoreException { - IUserManager userManager = (IUserManager)container.getElement("org.eclipse.net4j.userManagers", type, description); //$NON-NLS-1$ + IUserManager userManager = (IUserManager)container.getElement(UserManagerFactory.PRODUCT_GROUP, type, description); if (userManager == null) { throw new IllegalStateException("UserManager factory not found: " + type); //$NON-NLS-1$ @@ -232,6 +221,93 @@ public class RepositoryConfigurator return userManager; } + /** + * @since 4.2 + */ + @SuppressWarnings("deprecation") + protected void setUserManager(InternalRepository repository, Element repositoryConfig) throws CoreException + { + Element userManagerConfig = getUserManagerConfig(repositoryConfig); + if (userManagerConfig != null) + { + IUserManager userManager = getUserManager(userManagerConfig); + if (userManager != null) + { + InternalSessionManager sessionManager = repository.getSessionManager(); + if (sessionManager == null) + { + sessionManager = new SessionManager(); + repository.setSessionManager(sessionManager); + } + + sessionManager.setUserManager(userManager); + } + } + } + + /** + * @since 4.2 + */ + protected Element getAuthenticatorConfig(Element repositoryConfig) + { + NodeList authenticatorConfig = repositoryConfig.getElementsByTagName("authenticator"); //$NON-NLS-1$ + if (authenticatorConfig.getLength() > 1) + { + String repositoryName = repositoryConfig.getAttribute("name"); //$NON-NLS-1$ + throw new IllegalStateException("At most one authenticator must be configured for repository " + repositoryName); //$NON-NLS-1$ + } + + return (Element)(authenticatorConfig.getLength() > 0 ? authenticatorConfig.item(0) : null); + } + + /** + * @since 4.2 + */ + protected IAuthenticator getAuthenticator(Element authenticatorConfig) throws CoreException + { + String type = authenticatorConfig.getAttribute("type"); //$NON-NLS-1$ + String description = authenticatorConfig.getAttribute("description"); //$NON-NLS-1$ + return getAuthenticator(type, description); + } + + /** + * @since 4.2 + */ + protected IAuthenticator getAuthenticator(String type, String description) throws CoreException + { + IAuthenticator authenticator = (IAuthenticator)container.getElement(AuthenticatorFactory.PRODUCT_GROUP, type, + description); + if (authenticator == null) + { + throw new IllegalStateException("Authenticator factory not found: " + type); //$NON-NLS-1$ + } + + return authenticator; + } + + /** + * @since 4.2 + */ + protected void setAuthenticator(InternalRepository repository, Element repositoryConfig) throws CoreException + { + Element authenticatorConfig = getAuthenticatorConfig(repositoryConfig); + if (authenticatorConfig != null) + { + IAuthenticator authenticator = getAuthenticator(authenticatorConfig); + if (authenticator != null) + { + InternalSessionManager sessionManager = repository.getSessionManager(); + if (sessionManager == null) + { + sessionManager = new SessionManager(); + repository.setSessionManager(sessionManager); + } + + sessionManager.setAuthenticator(authenticator); + } + } + } + protected EPackage[] getInitialPackages(Element repositoryConfig) { List<EPackage> result = new ArrayList<EPackage>(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java index b497ac63ee..6720ab8fcd 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/RepositoryUserManager.java @@ -17,17 +17,21 @@ import org.eclipse.net4j.util.container.IElementProcessor; import org.eclipse.net4j.util.container.IManagedContainer; import org.eclipse.net4j.util.factory.ProductCreationException; import org.eclipse.net4j.util.lifecycle.Lifecycle; +import org.eclipse.net4j.util.security.AuthenticatorFactory; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.net4j.util.security.IUserManager; import org.eclipse.net4j.util.security.SecurityUtil; import org.eclipse.net4j.util.security.UserManagerFactory; +import java.util.Arrays; + /** * If the meaning of this type isn't clear, there really should be more of a description here... * * @author Eike Stepper * @since 4.0 */ -public abstract class RepositoryUserManager extends Lifecycle implements IUserManager +public abstract class RepositoryUserManager extends Lifecycle implements IUserManager, IAuthenticator { private IManagedContainer container; @@ -60,20 +64,9 @@ public abstract class RepositoryUserManager extends Lifecycle implements IUserMa public byte[] encrypt(String userID, byte[] data, String algorithmName, byte[] salt, int count) throws SecurityException { - IRepository repository = getRepository(container, repositoryName); - if (repository == null) - { - throw new SecurityException("Repository not found: " + repositoryName); //$NON-NLS-1$ - } - - char[] password = getPassword(repository, userID); - if (password == null) - { - throw new SecurityException("No such user: " + userID); //$NON-NLS-1$ - } - try { + char[] password = getPassword(userID); return SecurityUtil.encrypt(data, password, algorithmName, salt, count); } catch (RuntimeException ex) @@ -86,11 +79,42 @@ public abstract class RepositoryUserManager extends Lifecycle implements IUserMa } } + /** + * @since 4.2 + */ + public void authenticate(String userID, char[] password) throws SecurityException + { + char[] userPassword = getPassword(userID); + if (!Arrays.equals(password, userPassword)) + { + throw new SecurityException("Access denied"); //$NON-NLS-1$ + } + } + protected IRepository getRepository(IManagedContainer container, String repositoryName) { return CDOServerUtil.getRepository(container, repositoryName); } + /** + * @since 4.2 + */ + protected char[] getPassword(String userID) + { + IRepository repository = getRepository(container, repositoryName); + if (repository == null) + { + throw new SecurityException("Repository not found: " + repositoryName); //$NON-NLS-1$ + } + + char[] password = getPassword(repository, userID); + if (password == null) + { + throw new SecurityException("No such user: " + userID); //$NON-NLS-1$ + } + return password; + } + protected abstract char[] getPassword(IRepository repository, String userID); public static void prepareContainer(IManagedContainer container, RepositoryUserManagerFactory factory) @@ -131,6 +155,35 @@ public abstract class RepositoryUserManager extends Lifecycle implements IUserMa * If the meaning of this type isn't clear, there really should be more of a description here... * * @author Eike Stepper + * @since 4.2 + */ + public static abstract class RepositoryAuthenticatorFactory extends AuthenticatorFactory + { + protected RepositoryAuthenticatorFactory(String type) + { + super(type); + } + + public final Object create(String description) throws ProductCreationException + { + RepositoryUserManager userManager = doCreate(description); + String repositoryName = getRepositoryName(description); + userManager.setRepositoryName(repositoryName); + return userManager; + } + + protected String getRepositoryName(String description) + { + return description; + } + + protected abstract RepositoryUserManager doCreate(String description) throws ProductCreationException; + } + + /** + * If the meaning of this type isn't clear, there really should be more of a description here... + * + * @author Eike Stepper */ public static class RepositoryInjector implements IElementProcessor { diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CommitInfoTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CommitInfoTest.java index 1cf034564f..d80e79fc8c 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CommitInfoTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/CommitInfoTest.java @@ -100,7 +100,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); @@ -206,7 +206,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); @@ -332,7 +332,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); @@ -454,7 +454,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); @@ -568,7 +568,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); @@ -677,7 +677,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); @@ -786,7 +786,7 @@ public class CommitInfoTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java index 6df36ff5a7..4d1fa2ef02 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java @@ -25,7 +25,6 @@ import org.eclipse.emf.cdo.util.CommitException; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.net4j.signal.ISignalProtocol; -import org.eclipse.net4j.signal.RemoteException; import org.eclipse.net4j.signal.SignalProtocol.TimeoutChangedEvent; import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.container.ContainerEventAdapter; @@ -272,7 +271,7 @@ public class SessionTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD1); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); IRepository repository = getRepository("authrepo2"); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, @@ -292,17 +291,17 @@ public class SessionTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD1); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getRepository("authrepo3"); try { openSession("authrepo3"); - fail("RemoteException expected"); + fail("NotAuthenticatedException expected"); } - catch (RemoteException success) + catch (NotAuthenticatedException expected) { - assertEquals(SecurityException.class, success.getCause().getClass()); + // SUCCESS } } @@ -312,7 +311,7 @@ public class SessionTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD1); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getRepository("authrepo4"); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(null)); @@ -334,7 +333,7 @@ public class SessionTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD1); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getRepository("authrepo5"); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, @@ -343,11 +342,11 @@ public class SessionTest extends AbstractCDOTest try { openSession("authrepo5"); - fail("RemoteException expected"); + fail("SecurityException expected"); } - catch (RemoteException success) + catch (SecurityException expected) { - assertEquals(SecurityException.class, success.getCause().getClass()); + // SUCCESS } } @@ -357,7 +356,7 @@ public class SessionTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD1); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getRepository("authrepo6"); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, @@ -366,11 +365,11 @@ public class SessionTest extends AbstractCDOTest try { openSession("authrepo6"); - fail("RemoteException expected"); + fail("NotAuthenticatedException expected"); } - catch (RemoteException success) + catch (NotAuthenticatedException expected) { - assertEquals(SecurityException.class, success.getCause().getClass()); + // SUCCESS } } @@ -380,7 +379,7 @@ public class SessionTest extends AbstractCDOTest userManager.activate(); userManager.addUser(USER_ID, PASSWORD1); - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getRepository("authrepo7"); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, @@ -389,11 +388,11 @@ public class SessionTest extends AbstractCDOTest try { openSession("authrepo7"); - fail("RemoteException expected"); + fail("NotAuthenticatedException expected"); } - catch (RemoteException success) + catch (NotAuthenticatedException expected) { - assertEquals(SecurityException.class, success.getCause().getClass()); + // SUCCESS } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java index 5d106602a2..b3b01e9fca 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_343084_Test.java @@ -73,7 +73,7 @@ public class Bugzilla_343084_Test extends AbstractCDOTest } }; - getTestProperties().put(RepositoryConfig.PROP_TEST_USER_MANAGER, userManager); + getTestProperties().put(RepositoryConfig.PROP_TEST_AUTHENTICATOR, userManager); getTestProperties().put(RepositoryConfig.PROP_TEST_PERMISSION_MANAGER, permissionManager); getTestProperties().put(SessionConfig.PROP_TEST_CREDENTIALS_PROVIDER, new PasswordCredentialsProvider(new PasswordCredentials(USER_ID, PASSWORD))); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java index cb253ee31c..cb27d1c802 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java @@ -73,7 +73,7 @@ import org.eclipse.net4j.util.lifecycle.ILifecycle; import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.monitor.OMMonitor; -import org.eclipse.net4j.util.security.IUserManager; +import org.eclipse.net4j.util.security.IAuthenticator; import org.eclipse.net4j.util.tests.AbstractOMTest; import org.eclipse.emf.spi.cdo.InternalCDOSession; @@ -98,7 +98,7 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf public static final String PROP_TEST_SESSION_MANAGER = "test.repository.SessionManager"; - public static final String PROP_TEST_USER_MANAGER = "test.repository.UserManager"; + public static final String PROP_TEST_AUTHENTICATOR = "test.repository.Authenticator"; public static final String PROP_TEST_PERMISSION_MANAGER = "test.repository.PermissionManager"; @@ -514,10 +514,10 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf repository.setSessionManager(sessionManager); - IUserManager userManager = getTestUserManager(); - if (userManager != null) + IAuthenticator authenticator = getTestAuthenticator(); + if (authenticator != null) { - sessionManager.setUserManager(userManager); + sessionManager.setAuthenticator(authenticator); } IPermissionManager permissionManager = getTestPermissionManager(); @@ -559,9 +559,9 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf return (InternalSessionManager)getTestProperty(PROP_TEST_SESSION_MANAGER); } - protected IUserManager getTestUserManager() + protected IAuthenticator getTestAuthenticator() { - return (IUserManager)getTestProperty(PROP_TEST_USER_MANAGER); + return (IAuthenticator)getTestProperty(PROP_TEST_AUTHENTICATOR); } protected IPermissionManager getTestPermissionManager() diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java index 0931d8f201..8922a07be9 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java @@ -106,7 +106,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig IPasswordCredentialsProvider credentialsProvider = getTestCredentialsProvider(); if (credentialsProvider != null) { - configuration.getAuthenticator().setCredentialsProvider(credentialsProvider); + configuration.setCredentialsProvider(credentialsProvider); } CDOSession session = configuration.openSession(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestSessionConfiguration.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestSessionConfiguration.java index 21cbcefd8a..8620f87360 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestSessionConfiguration.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestSessionConfiguration.java @@ -13,12 +13,12 @@ package org.eclipse.emf.cdo.tests.util; import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode; import org.eclipse.emf.cdo.common.CDOCommonSession.Options.PassiveUpdateMode; import org.eclipse.emf.cdo.common.id.CDOIDGenerator; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.session.CDOSessionConfiguration; import org.eclipse.emf.cdo.view.CDOFetchRuleManager; import org.eclipse.net4j.util.event.Notifier; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; /** * @author Eike Stepper @@ -50,7 +50,18 @@ public abstract class TestSessionConfiguration extends Notifier implements CDOSe throw new UnsupportedOperationException(); } - public CDOAuthenticator getAuthenticator() + @Deprecated + public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator() + { + throw new UnsupportedOperationException(); + } + + public IPasswordCredentialsProvider getCredentialsProvider() + { + throw new UnsupportedOperationException(); + } + + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider) { throw new UnsupportedOperationException(); } diff --git a/plugins/org.eclipse.emf.cdo.ui.admin/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.ui.admin/META-INF/MANIFEST.MF index 723324888f..6731712a98 100644 --- a/plugins/org.eclipse.emf.cdo.ui.admin/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.ui.admin/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.ui.admin;singleton:=true -Bundle-Version: 4.1.0.qualifier +Bundle-Version: 4.1.100.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -15,5 +15,5 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)", org.eclipse.net4j.ui;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, org.eclipse.emf.cdo.ui.shared;bundle-version="[4.0.0,5.0.0)", org.eclipse.net4j.ui.shared;bundle-version="[4.0.0,5.0.0)" -Export-Package: org.eclipse.emf.cdo.ui.internal.admin;version="4.1.0";x-internal:=true, - org.eclipse.emf.cdo.ui.internal.admin.bundle;version="4.1.0";x-internal:=true +Export-Package: org.eclipse.emf.cdo.ui.internal.admin;version="4.1.100";x-internal:=true, + org.eclipse.emf.cdo.ui.internal.admin.bundle;version="4.1.100";x-internal:=true diff --git a/plugins/org.eclipse.emf.cdo.ui.admin/src/org/eclipse/emf/cdo/ui/internal/admin/CDOAdminView.java b/plugins/org.eclipse.emf.cdo.ui.admin/src/org/eclipse/emf/cdo/ui/internal/admin/CDOAdminView.java index 495f97ab59..7e2452c5c0 100644 --- a/plugins/org.eclipse.emf.cdo.ui.admin/src/org/eclipse/emf/cdo/ui/internal/admin/CDOAdminView.java +++ b/plugins/org.eclipse.emf.cdo.ui.admin/src/org/eclipse/emf/cdo/ui/internal/admin/CDOAdminView.java @@ -310,7 +310,7 @@ public class CDOAdminView extends ContainerView public void prepare(CDONet4jSessionConfiguration configuration) { IPasswordCredentialsProvider credentialsProvider = getCredentialsProvider(); - configuration.getAuthenticator().setCredentialsProvider(credentialsProvider); + configuration.setCredentialsProvider(credentialsProvider); } } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSessionConfiguration.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSessionConfiguration.java index 5a5b66a33e..fdafe5d855 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSessionConfiguration.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/session/CDOSessionConfiguration.java @@ -13,11 +13,11 @@ package org.eclipse.emf.cdo.session; import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode; import org.eclipse.emf.cdo.common.CDOCommonSession.Options.PassiveUpdateMode; import org.eclipse.emf.cdo.common.id.CDOIDGenerator; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.view.CDOFetchRuleManager; import org.eclipse.net4j.util.event.IEvent; import org.eclipse.net4j.util.event.INotifier; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; /** * Configures and opens new {@link CDOSession sessions}. @@ -125,8 +125,21 @@ public interface CDOSessionConfiguration extends INotifier /** * Returns the authenticator of this configuration, never <code>null</code>. + * + * @deprecated As of 4.2 use {@link #getCredentialsProvider()} and {@link #setCredentialsProvider(IPasswordCredentialsProvider)}, respectively + */ + @Deprecated + public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator(); + + /** + * @since 4.2 + */ + public IPasswordCredentialsProvider getCredentialsProvider(); + + /** + * @since 4.2 */ - public CDOAuthenticator getAuthenticator(); + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider); /** * Returns <code>true</code> if the session opened by {@link #openSession()} will be automatically activated, diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOAuthenticatorImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOAuthenticatorImpl.java index 79a1bf13df..295cb1a476 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOAuthenticatorImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOAuthenticatorImpl.java @@ -10,9 +10,6 @@ */ package org.eclipse.emf.internal.cdo.session; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; -import org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult; - import org.eclipse.net4j.util.security.IPasswordCredentials; import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.net4j.util.security.SecurityUtil; @@ -20,7 +17,8 @@ import org.eclipse.net4j.util.security.SecurityUtil; /** * @author Eike Stepper */ -public class CDOAuthenticatorImpl implements CDOAuthenticator +@Deprecated +public class CDOAuthenticatorImpl implements org.eclipse.emf.cdo.common.protocol.CDOAuthenticator { private String encryptionAlgorithmName = SecurityUtil.PBE_WITH_MD5_AND_DES; @@ -74,7 +72,7 @@ public class CDOAuthenticatorImpl implements CDOAuthenticator this.credentialsProvider = credentialsProvider; } - public CDOAuthenticationResult authenticate(byte[] randomToken) + public org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult authenticate(byte[] randomToken) { if (credentialsProvider == null) { @@ -86,7 +84,7 @@ public class CDOAuthenticatorImpl implements CDOAuthenticator { String userID = credentials.getUserID(); byte[] cryptedToken = encryptToken(credentials.getPassword(), randomToken); - return new CDOAuthenticationResult(userID, cryptedToken); + return new org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult(userID, cryptedToken); } return null; diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionConfigurationImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionConfigurationImpl.java index 18a2ced401..e723e0e3f2 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionConfigurationImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionConfigurationImpl.java @@ -16,7 +16,6 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchManager; import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager; import org.eclipse.emf.cdo.common.id.CDOIDGenerator; import org.eclipse.emf.cdo.common.model.CDOPackageRegistry; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.common.revision.CDORevisionManager; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.session.CDOSessionConfiguration; @@ -32,6 +31,7 @@ import org.eclipse.net4j.util.event.IListener; import org.eclipse.net4j.util.event.Notifier; import org.eclipse.net4j.util.lifecycle.ILifecycle; import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.emf.spi.cdo.InternalCDOSession; import org.eclipse.emf.spi.cdo.InternalCDOSessionConfiguration; @@ -49,7 +49,7 @@ public abstract class CDOSessionConfigurationImpl extends Notifier implements In private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS; - private CDOAuthenticator authenticator = new CDOAuthenticatorImpl(); + private IPasswordCredentialsProvider credentialsProvider; private CDOSession.ExceptionHandler exceptionHandler; @@ -155,15 +155,64 @@ public abstract class CDOSessionConfigurationImpl extends Notifier implements In this.lockNotificationMode = lockNotificationMode; } - public CDOAuthenticator getAuthenticator() + @Deprecated + public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator() { - return authenticator; + return new org.eclipse.emf.cdo.common.protocol.CDOAuthenticator() + { + public String getEncryptionAlgorithmName() + { + return null; + } + + public void setEncryptionAlgorithmName(String encryptionAlgorithmName) + { + } + + public byte[] getEncryptionSaltBytes() + { + return null; + } + + public void setEncryptionSaltBytes(byte[] encryptionSaltBytes) + { + } + + public int getEncryptionIterationCount() + { + return 0; + } + + public void setEncryptionIterationCount(int encryptionIterationCount) + { + } + + public IPasswordCredentialsProvider getCredentialsProvider() + { + return CDOSessionConfigurationImpl.this.getCredentialsProvider(); + } + + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider) + { + CDOSessionConfigurationImpl.this.setCredentialsProvider(credentialsProvider); + } + + public org.eclipse.emf.cdo.spi.common.CDOAuthenticationResult authenticate(byte[] randomToken) + { + throw new UnsupportedOperationException(); + } + }; + } + + public IPasswordCredentialsProvider getCredentialsProvider() + { + return credentialsProvider; } - public void setAuthenticator(CDOAuthenticator authenticator) + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider) { checkNotOpen(); - this.authenticator = authenticator; + this.credentialsProvider = credentialsProvider; } public CDOSession.ExceptionHandler getExceptionHandler() @@ -324,7 +373,7 @@ public abstract class CDOSessionConfigurationImpl extends Notifier implements In session.setExceptionHandler(exceptionHandler); session.setFetchRuleManager(fetchRuleManager); session.setIDGenerator(idGenerator); - session.setAuthenticator(authenticator); + session.setCredentialsProvider(credentialsProvider); session.setRevisionManager(revisionManager); session.setBranchManager(branchManager); session.setCommitInfoManager(commitInfoManager); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java index c773c24cfc..a6b38604a7 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -31,7 +31,6 @@ import org.eclipse.emf.cdo.common.lob.CDOLobStore; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.model.EMFUtil; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.common.revision.CDOElementProxy; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDOList; @@ -109,6 +108,7 @@ import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.log.OMLogger; import org.eclipse.net4j.util.options.OptionsEvent; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.emf.common.util.ECollections; import org.eclipse.emf.ecore.EPackage; @@ -197,7 +197,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme private boolean mainBranchLocal; - private CDOAuthenticator authenticator; + private IPasswordCredentialsProvider credentialsProvider; private InternalCDORemoteSessionManager remoteSessionManager; @@ -365,14 +365,26 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme this.fetchRuleManager = fetchRuleManager; } - public CDOAuthenticator getAuthenticator() + @Deprecated + public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator() + { + throw new UnsupportedOperationException(); + } + + @Deprecated + public void setAuthenticator(org.eclipse.emf.cdo.common.protocol.CDOAuthenticator authenticator) + { + throw new UnsupportedOperationException(); + } + + public IPasswordCredentialsProvider getCredentialsProvider() { - return authenticator; + return credentialsProvider; } - public void setAuthenticator(CDOAuthenticator authenticator) + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider) { - this.authenticator = authenticator; + this.credentialsProvider = credentialsProvider; } public boolean isMainBranchLocal() diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java index 4b8e402640..f5755eebe7 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java @@ -19,7 +19,6 @@ import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDGenerator; import org.eclipse.emf.cdo.common.lob.CDOLobStore; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; -import org.eclipse.emf.cdo.common.protocol.CDOAuthenticator; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.session.CDORepositoryInfo; import org.eclipse.emf.cdo.session.CDOSession; @@ -36,6 +35,7 @@ import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager.Revisi import org.eclipse.emf.cdo.view.CDOFetchRuleManager; import org.eclipse.net4j.util.lifecycle.ILifecycle; +import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult; @@ -63,13 +63,27 @@ public interface InternalCDOSession extends CDOSession, PackageProcessor, Packag /** * @since 4.0 + * @deprecated As of 4.2 use {@link #getCredentialsProvider()} */ - public CDOAuthenticator getAuthenticator(); + @Deprecated + public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator(); /** * @since 4.0 + * @deprecated As of 4.2 use {@link #setCredentialsProvider(IPasswordCredentialsProvider)} + */ + @Deprecated + public void setAuthenticator(org.eclipse.emf.cdo.common.protocol.CDOAuthenticator authenticator); + + /** + * @since 4.2 + */ + public IPasswordCredentialsProvider getCredentialsProvider(); + + /** + * @since 4.2 */ - public void setAuthenticator(CDOAuthenticator authenticator); + public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider); public InternalCDOPackageRegistry getPackageRegistry(); diff --git a/plugins/org.eclipse.net4j.util/plugin.xml b/plugins/org.eclipse.net4j.util/plugin.xml index 0250e90a0d..0a37bfac35 100644 --- a/plugins/org.eclipse.net4j.util/plugin.xml +++ b/plugins/org.eclipse.net4j.util/plugin.xml @@ -6,7 +6,7 @@ are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html - + Contributors: Eike Stepper - initial API and implementation --> @@ -15,7 +15,7 @@ <extension-point id="factories" name="%extension-point.name" schema="schema/factories.exsd"/> <extension-point id="elementProcessors" name="%extension-point.name.0" schema="schema/elementProcessors.exsd"/> - + <extension point="org.eclipse.net4j.util.factories"> <factory @@ -34,6 +34,10 @@ productGroup="org.eclipse.net4j.userManagers" type="file" class="org.eclipse.net4j.util.security.FileUserManagerFactory"/> + <factory + productGroup="org.eclipse.net4j.authenticators" + type="file" + class="org.eclipse.net4j.util.security.FileAuthenticatorFactory"/> </extension> </plugin> diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/AuthenticatorFactory.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/AuthenticatorFactory.java new file mode 100644 index 0000000000..6aadef0b5d --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/AuthenticatorFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.util.security; + +import org.eclipse.net4j.util.factory.Factory; + +/** + * @author Eike Stepper + * @since 3.3 + */ +public abstract class AuthenticatorFactory extends Factory +{ + public static final String PRODUCT_GROUP = "org.eclipse.net4j.authenticators"; //$NON-NLS-1$ + + public AuthenticatorFactory(String type) + { + super(PRODUCT_GROUP, type); + } +} diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java new file mode 100644 index 0000000000..b484fd22ca --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.util.security; + +import org.eclipse.net4j.util.io.ExtendedDataInput; +import org.eclipse.net4j.util.io.ExtendedDataOutput; +import org.eclipse.net4j.util.io.IORuntimeException; + +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import javax.crypto.SecretKey; +import javax.crypto.interfaces.DHPublicKey; +import javax.crypto.spec.DHParameterSpec; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.AlgorithmParameterGenerator; +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PublicKey; +import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; + +/** + * Executes the Diffie-Hellman key agreement protocol between 2 parties: {@link Server} and {@link Client}. + * + * @author Eike Stepper + * @since 3.3 + */ +public class DiffieHellman +{ + public static void main(String argv[]) throws Exception + { + byte[] clearText = "This is just an example".getBytes(); + + // Server server = new Server(SkipParameterSpec.INSTANCE, "DES", "DES/ECB/PKCS5Padding"); + Server server = new Server(SkipParameterSpec.INSTANCE, "DES", "DES/CBC/PKCS5Padding"); + Client client = new Client(); + + Server.Challenge challenge = server.getChallenge(); + Client.Response result = client.handleChallenge(challenge, clearText); + byte[] recovered = server.handleResponse(result); + + if (!Arrays.equals(clearText, recovered)) + { + throw new Exception("Recovered text is different from cleartext"); + } + + System.out.println("Recovered text is same as cleartext"); + } + + /** + * Executes the server-side of the Diffie-Hellman key agreement protocol. + * + * @author Eike Stepper + */ + public static class Server + { + public static final String DEFAULT_SECRET_ALGORITHM = "DES"; + + public static final String DEFAULT_CYPHER_TRANSFORMATION = "DES/CBC/PKCS5Padding"; + + private final KeyAgreement keyAgree; + + private final Challenge challenge; + + public Server(DHParameterSpec dhParamSpec, String secretAlgorithm, String cypherTransformation) + { + try + { + // Create DH key pair, using the passed DH parameters + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH"); + keyPairGenerator.initialize(dhParamSpec); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + + // Create and initialize DH KeyAgreement object + keyAgree = KeyAgreement.getInstance("DH"); + keyAgree.init(keyPair.getPrivate()); + + // Encode public key + byte[] pubKeyEnc = keyPair.getPublic().getEncoded(); + + // Create and remember Challenge object + challenge = new Challenge(secretAlgorithm, cypherTransformation, pubKeyEnc); + } + catch (GeneralSecurityException ex) + { + throw new SecurityException(ex); + } + } + + public Server(DHParameterSpec dhParamSpec) + { + this(dhParamSpec, DEFAULT_SECRET_ALGORITHM, DEFAULT_CYPHER_TRANSFORMATION); + } + + public Server() + { + this(SkipParameterSpec.INSTANCE); + } + + public final Challenge getChallenge() + { + return challenge; + } + + public byte[] handleResponse(Client.Response response) + { + try + { + // Instantiate a DH public key from the client's encoded key material. + KeyFactory keyFactory = KeyFactory.getInstance("DH"); + X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(response.getClientPubKeyEnc()); + PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); + + // Use Client's public key for the first (and only) phase of her version of the DH protocol. + keyAgree.doPhase(pubKey, true); + SecretKey sharedSecret = keyAgree.generateSecret(challenge.getSecretAlgorithm()); + + // Prepare the cipher used to decrypt + Cipher serverCipher = Cipher.getInstance(challenge.getCypherTransformation()); + + byte[] encodedParams = response.getParamsEnc(); + if (encodedParams == null) + { + serverCipher.init(Cipher.DECRYPT_MODE, sharedSecret); + } + else + { + // Instantiate AlgorithmParameters object from parameter encoding obtained from client + AlgorithmParameters params = AlgorithmParameters.getInstance(challenge.getSecretAlgorithm()); + params.init(encodedParams); + + serverCipher.init(Cipher.DECRYPT_MODE, sharedSecret, params); + } + + // Decrypt + return serverCipher.doFinal(response.getCipherText()); + } + catch (GeneralSecurityException ex) + { + throw new SecurityException(ex); + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + } + + /** + * @author Eike Stepper + */ + public static final class Challenge + { + private final String secretAlgorithm; + + private final String cypherTransformation; + + private final byte[] serverPubKeyEnc; + + public Challenge(String secretAlgorithm, String cypherTransformation, byte[] serverPubKeyEnc) + { + this.secretAlgorithm = secretAlgorithm; + this.cypherTransformation = cypherTransformation; + this.serverPubKeyEnc = serverPubKeyEnc; + } + + public Challenge(ExtendedDataInput in) throws IOException + { + secretAlgorithm = in.readString(); + cypherTransformation = in.readString(); + serverPubKeyEnc = in.readByteArray(); + } + + public void write(ExtendedDataOutput out) throws IOException + { + out.writeString(secretAlgorithm); + out.writeString(cypherTransformation); + out.writeByteArray(serverPubKeyEnc); + } + + public String getSecretAlgorithm() + { + return secretAlgorithm; + } + + public String getCypherTransformation() + { + return cypherTransformation; + } + + public byte[] getServerPubKeyEnc() + { + return serverPubKeyEnc; + } + } + } + + /** + * Executes the client-side of the Diffie-Hellman key agreement protocol. + * + * @author Eike Stepper + */ + public static class Client + { + public Client() + { + } + + public Response handleChallenge(Server.Challenge challenge, byte[] clearText) + { + try + { + KeyFactory keyFactory = KeyFactory.getInstance("DH"); + X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(challenge.getServerPubKeyEnc()); + PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); + + // Use the DH parameters associated with the server's public key to generate own key pair + DHParameterSpec dhParamSpec = ((DHPublicKey)pubKey).getParams(); + + // Create own DH key pair + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH"); + keyPairGenerator.initialize(dhParamSpec); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + + // Create and initialize DH KeyAgreement object + KeyAgreement clientKeyAgree = KeyAgreement.getInstance("DH"); + clientKeyAgree.init(keyPair.getPrivate()); + + // Encode public key + byte[] pubKeyEnc = keyPair.getPublic().getEncoded(); + + // Use server's public key for the first (and only) phase of his version of the DH protocol + clientKeyAgree.doPhase(pubKey, true); + SecretKey sharedSecret = clientKeyAgree.generateSecret(challenge.getSecretAlgorithm()); + + // Encrypt + Cipher clientCipher = Cipher.getInstance(challenge.getCypherTransformation()); + clientCipher.init(Cipher.ENCRYPT_MODE, sharedSecret); + byte[] ciphertext = clientCipher.doFinal(clearText); + + // Retrieve the parameter that was used, and transfer it to the server in encoded format + AlgorithmParameters params = clientCipher.getParameters(); + byte[] paramsEnc = params == null ? null : params.getEncoded(); + + return new Response(pubKeyEnc, ciphertext, paramsEnc); + } + catch (GeneralSecurityException ex) + { + throw new SecurityException(ex); + } + catch (IOException ex) + { + throw new IORuntimeException(ex); + } + } + + /** + * @author Eike Stepper + */ + public static final class Response + { + private final byte[] clientPubKeyEnc; + + private final byte[] cipherText; + + private final byte[] paramsEnc; + + public Response(byte[] clientPubKeyEnc, byte[] cipherText, byte[] paramsEnc) + { + this.clientPubKeyEnc = clientPubKeyEnc; + this.cipherText = cipherText; + this.paramsEnc = paramsEnc; + } + + public Response(ExtendedDataInput in) throws IOException + { + clientPubKeyEnc = in.readByteArray(); + cipherText = in.readByteArray(); + paramsEnc = in.readByteArray(); + } + + public void write(ExtendedDataOutput out) throws IOException + { + out.writeByteArray(clientPubKeyEnc); + out.writeByteArray(cipherText); + out.writeByteArray(paramsEnc); + } + + public byte[] getClientPubKeyEnc() + { + return clientPubKeyEnc; + } + + public byte[] getCipherText() + { + return cipherText; + } + + public byte[] getParamsEnc() + { + return paramsEnc; + } + } + } + + /** + * @author Eike Stepper + */ + public static final class SkipParameterSpec + { + /** + * The 1024 bit Diffie-Hellman modulus values used by SKIP + */ + private static final byte skip1024ModulusBytes[] = { (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58, (byte)0x4E, + (byte)0x49, (byte)0xDB, (byte)0xCD, (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4, (byte)0x91, (byte)0x07, + (byte)0x36, (byte)0x6B, (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D, (byte)0x45, (byte)0x1D, (byte)0x0F, + (byte)0x7C, (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C, (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6, + (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0, (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B, (byte)0x18, + (byte)0x8D, (byte)0x8E, (byte)0xBB, (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D, (byte)0x38, (byte)0xD3, + (byte)0x34, (byte)0xFD, (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43, (byte)0xA3, (byte)0x1D, (byte)0x18, + (byte)0x6C, (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C, (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C, + (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40, (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C, (byte)0x84, + (byte)0xA7, (byte)0x0A, (byte)0x72, (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03, (byte)0x19, (byte)0xC8, + (byte)0x07, (byte)0x29, (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C, (byte)0xD9, (byte)0x96, (byte)0x9F, + (byte)0xAB, (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B, (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08, + (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D, (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C, (byte)0xBD, + (byte)0x89, (byte)0x4B, (byte)0x22, (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB, (byte)0xA2, (byte)0x5E, + (byte)0xC3, (byte)0x55, (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7 }; + + /** + * The SKIP 1024 bit modulus + */ + private static final BigInteger skip1024Modulus = new BigInteger(1, skip1024ModulusBytes); + + /** + * The base used with the SKIP 1024 bit modulus + */ + private static final BigInteger skip1024Base = BigInteger.valueOf(2); + + public static final DHParameterSpec INSTANCE = new DHParameterSpec(skip1024Modulus, skip1024Base); + } + + /** + * Creates Diffie-Hellman parameters. + * + * @author Eike Stepper + */ + public static final class ParameterSpecGenerator + { + /** + * Create Diffie-Hellman parameters. + * <p> + * Takes VERY long... + */ + public static DHParameterSpec generate(int bits) + { + try + { + AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH"); + paramGen.init(bits); + + AlgorithmParameters params = paramGen.generateParameters(); + return params.getParameterSpec(DHParameterSpec.class); + } + catch (GeneralSecurityException ex) + { + throw new SecurityException(ex); + } + } + } +} diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java new file mode 100644 index 0000000000..24c10df412 --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.util.security; + +/** + * TODO Consider file attributes when creating initially empty file + * + * @author Eike Stepper + * @since 3.3 + */ +public class FileAuthenticatorFactory extends AuthenticatorFactory +{ + public static final String TYPE = "file"; //$NON-NLS-1$ + + public FileAuthenticatorFactory() + { + super(TYPE); + } + + public FileUserManager create(String description) + { + FileUserManager userManager = new FileUserManager(); + userManager.setFileName(description); + return userManager; + } +} diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/IAuthenticator.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/IAuthenticator.java new file mode 100644 index 0000000000..f38df4585f --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/IAuthenticator.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.util.security; + +/** + * Authenticates users. + * + * @author Eike Stepper + * @since 3.3 + */ +public interface IAuthenticator +{ + /** + * Authenticates the user with the passed <code>userID</code> by checking whether the supplied <code>password</code> + * matches the password <i>stored</i> for this user. + * <p> + * The implementation is required to throw a {@link SecurityException} if the passwords do <b>not</b> match. + */ + public void authenticate(String userID, char[] password) throws SecurityException; +} diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java index 03d8752097..f7f1b61ee8 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java @@ -14,13 +14,14 @@ import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; import org.eclipse.net4j.util.io.IORuntimeException; import org.eclipse.net4j.util.lifecycle.Lifecycle; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * @author Eike Stepper */ -public class UserManager extends Lifecycle implements IUserManager +public class UserManager extends Lifecycle implements IUserManager, IAuthenticator { @ExcludeFromDump protected transient Map<String, char[]> users = new HashMap<String, char[]>(); @@ -44,6 +45,36 @@ public class UserManager extends Lifecycle implements IUserManager } /** + * @since 3.3 + */ + public char[] getPassword(String userID) + { + return users.get(userID); + } + + /** + * @since 3.3 + */ + public void authenticate(String userID, char[] password) + { + char[] userPassword; + synchronized (this) + { + userPassword = users.get(userID); + } + + if (userPassword == null) + { + throw new SecurityException("No such user: " + userID); //$NON-NLS-1$ + } + + if (!Arrays.equals(userPassword, password)) + { + throw new SecurityException("Wrong password for user: " + userID); //$NON-NLS-1$ + } + } + + /** * @since 2.0 */ public byte[] encrypt(String userID, byte[] data, String algorithmName, byte[] salt, int count) diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerAuthenticator.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerAuthenticator.java new file mode 100644 index 0000000000..235ff76faf --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerAuthenticator.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.util.security; + +import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; +import org.eclipse.net4j.util.lifecycle.Lifecycle; +import org.eclipse.net4j.util.lifecycle.LifecycleUtil; + +import java.util.Arrays; + +/** + * @author Eike Stepper + * @since 3.3 + */ +public class UserManagerAuthenticator extends Lifecycle implements IAuthenticator +{ + public static final int DEFAULT_TOKEN_LENGTH = 1024; + + @ExcludeFromDump + private String encryptionAlgorithmName = SecurityUtil.PBE_WITH_MD5_AND_DES; + + @ExcludeFromDump + private byte[] encryptionSaltBytes = SecurityUtil.DEFAULT_SALT; + + @ExcludeFromDump + private int encryptionIterationCount = SecurityUtil.DEFAULT_ITERATION_COUNT; + + private int tokenLength = DEFAULT_TOKEN_LENGTH; + + private IRandomizer randomizer; + + private IUserManager userManager; + + public UserManagerAuthenticator() + { + } + + public String getEncryptionAlgorithmName() + { + return encryptionAlgorithmName; + } + + public void setEncryptionAlgorithmName(String encryptionAlgorithmName) + { + checkInactive(); + this.encryptionAlgorithmName = encryptionAlgorithmName; + } + + public byte[] getEncryptionSaltBytes() + { + return encryptionSaltBytes; + } + + public void setEncryptionSaltBytes(byte[] encryptionSaltBytes) + { + checkInactive(); + this.encryptionSaltBytes = encryptionSaltBytes; + } + + public int getEncryptionIterationCount() + { + return encryptionIterationCount; + } + + public void setEncryptionIterationCount(int encryptionIterationCount) + { + checkInactive(); + this.encryptionIterationCount = encryptionIterationCount; + } + + public int getTokenLength() + { + return tokenLength; + } + + public void setTokenLength(int tokenLength) + { + checkInactive(); + this.tokenLength = tokenLength; + } + + public IRandomizer getRandomizer() + { + return randomizer; + } + + public void setRandomizer(IRandomizer randomizer) + { + checkInactive(); + this.randomizer = randomizer; + } + + public IUserManager getUserManager() + { + return userManager; + } + + public void setUserManager(IUserManager userManager) + { + checkInactive(); + this.userManager = userManager; + } + + public void authenticate(String userID, char[] password) throws SecurityException + { + try + { + byte[] randomToken = createRandomToken(); + byte[] cryptedTokenClient = SecurityUtil.encrypt(randomToken, password, encryptionAlgorithmName, + encryptionSaltBytes, encryptionIterationCount); + + byte[] cryptedTokenServer = userManager.encrypt(userID, randomToken, encryptionAlgorithmName, + encryptionSaltBytes, encryptionIterationCount); + + if (!Arrays.equals(cryptedTokenClient, cryptedTokenServer)) + { + throw new SecurityException("Access denied"); //$NON-NLS-1$ + } + } + catch (SecurityException ex) + { + throw ex; + } + catch (Exception ex) + { + Throwable cause = ex.getCause(); + if (cause instanceof SecurityException) + { + throw (SecurityException)cause; + } + + throw new SecurityException(ex); + } + } + + @Override + protected void doBeforeActivate() throws Exception + { + super.doBeforeActivate(); + checkState(userManager, "userManager"); + } + + @Override + protected void doActivate() throws Exception + { + super.doActivate(); + + if (randomizer == null) + { + randomizer = new Randomizer(); + } + + LifecycleUtil.activate(randomizer); + } + + protected byte[] createRandomToken() + { + byte[] token = new byte[tokenLength]; + randomizer.nextBytes(token); + return token; + } +} diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerFactory.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerFactory.java index 5b03f1f1e6..44feb6f11f 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerFactory.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManagerFactory.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ |