blob: 527cffd8510e9c0a69d290acf484f5919e87f9ca [file] [log] [blame]
/*
* Copyright (c) 2013, 2016 Eike Stepper (Loehne, 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
* Christian W. Damus (CEA LIST) - Adapted from AuthenticationIndication for 399306
*/
package org.eclipse.emf.cdo.internal.net4j.protocol;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
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.CredentialsUpdateOperation;
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.IPasswordCredentialsProvider;
import org.eclipse.net4j.util.security.IPasswordCredentialsUpdate;
import org.eclipse.net4j.util.security.IPasswordCredentialsUpdateProvider;
import org.eclipse.emf.spi.cdo.InternalCDOSession;
import java.io.ByteArrayOutputStream;
/**
* Implementation of the CDO client handler for the server-initiated change-credentials protocol.
*
* @author Christian W. Damus (CEA LIST)
*/
public class CredentialsChallengeIndication extends IndicationWithMonitoring
{
private Challenge challenge;
private CredentialsUpdateOperation operation;
private String userID;
public CredentialsChallengeIndication(SignalProtocol<?> protocol)
{
super(protocol, CDOProtocolConstants.SIGNAL_CREDENTIALS_CHALLENGE);
}
@Override
public CDOClientProtocol getProtocol()
{
return (CDOClientProtocol)super.getProtocol();
}
protected InternalCDOSession getSession()
{
return (InternalCDOSession)getProtocol().getSession();
}
@Override
protected int getIndicatingWorkPercent()
{
return 1;
}
@Override
protected void indicating(ExtendedDataInputStream in, OMMonitor monitor) throws Exception
{
operation = in.readEnum(CredentialsUpdateOperation.class);
userID = in.readString(); // May be null if operation is not reset
challenge = new Challenge(in);
}
@Override
protected void responding(ExtendedDataOutputStream out, OMMonitor monitor) throws Exception
{
monitor.begin();
Async async = monitor.forkAsync();
try
{
IPasswordCredentialsProvider credentialsProvider = getSession().getCredentialsProvider();
if (!(credentialsProvider instanceof IPasswordCredentialsUpdateProvider))
{
throw new IllegalStateException("No credentials update provider configured"); //$NON-NLS-1$
}
IPasswordCredentialsUpdate credentials = ((IPasswordCredentialsUpdateProvider)credentialsProvider).getCredentialsUpdate(userID, operation);
if (credentials == null)
{
// User canceled. Fine
out.writeBoolean(false);
return;
}
String authUserID = credentials.getUserID();
String authPassword = new String(credentials.getPassword());
String newPassword = new String(credentials.getNewPassword());
if (StringUtil.isEmpty(newPassword))
{
throw new IllegalStateException("No new password provided"); //$NON-NLS-1$
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ExtendedDataOutputStream stream = new ExtendedDataOutputStream(baos);
switch (operation)
{
case CHANGE_PASSWORD:
stream.writeString(authUserID);
stream.writeString(authPassword);
stream.writeString(newPassword);
break;
case RESET_PASSWORD:
stream.writeString(authUserID);
stream.writeString(authPassword);
stream.writeString(userID);
stream.writeString(newPassword);
break;
}
stream.close();
byte[] clearText = baos.toByteArray();
DiffieHellman.Client client = new DiffieHellman.Client();
Response response = client.handleChallenge(challenge, clearText);
out.writeBoolean(true);
response.write(out);
}
catch (Throwable ex)
{
out.writeBoolean(false);
OM.LOG.error(ex);
}
finally
{
async.stop();
monitor.done();
}
}
}