/*
* dCache - http://www.dcache.org/
*
* Copyright (C) 2016 Deutsches Elektronen-Synchrotron
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package dmg.cells.services.login;
import com.google.common.util.concurrent.AbstractService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import dmg.cells.nucleus.Cell;
import dmg.cells.nucleus.CellEndpoint;
import dmg.util.StreamEngine;
import org.dcache.auth.Subjects;
import org.dcache.util.Args;
public abstract class StreamEngineLoginCellFactory extends AbstractService implements LoginCellFactory
{
private static final Logger LOGGER = LoggerFactory.getLogger(LoginManager.class);
private static final Class<?>[] AUTH_CON_SIGNATURE =
{ CellEndpoint.class, Args.class };
private final Args args;
private final String protocol;
private final Constructor<?> authConstructor;
private final Class<?> authClass;
private final CellEndpoint endpoint;
public StreamEngineLoginCellFactory(Args args, CellEndpoint endpoint)
{
this.args = args;
this.endpoint = endpoint;
protocol = checkProtocol(args.getOpt("prot"));
LOGGER.info("Using protocol : {}", protocol);
try {
authClass = toAuthClass(args.getOpt("auth"), protocol);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("No such class: " + args.getOpt("auth"));
}
Constructor<?> authConstructor;
if (authClass != null) {
try {
authConstructor = authClass.getConstructor(AUTH_CON_SIGNATURE);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Class lacks authentication constructor: " + authClass);
}
LOGGER.trace("Using authentication constructor: {}", authConstructor);
} else {
authConstructor = null;
LOGGER.trace("No authentication used");
}
this.authConstructor = authConstructor;
}
private static String checkProtocol(String protocol) throws IllegalArgumentException
{
if (protocol == null) {
protocol = "telnet";
}
if (!protocol.equals("telnet") && !protocol.equals("raw")) {
throw new IllegalArgumentException("Protocol must be telnet or raw");
}
return protocol;
}
private static Class<?> toAuthClass(String authClassName, String protocol) throws ClassNotFoundException
{
Class<?> authClass = null;
if (authClassName == null) {
switch (protocol) {
case "raw":
authClass = null;
break;
case "telnet":
authClass = TelnetSAuth_A.class;
break;
}
} else if (!authClassName.equals("none")) {
authClass = Class.forName(authClassName);
}
if (authClass != null) {
LOGGER.info("Using authentication Module: {}", authClass);
}
return authClass;
}
@Override
public Cell newCell(Socket socket) throws InvocationTargetException
{
StreamEngine engine;
try {
if (authConstructor != null) {
engine = StreamEngineFactory.newStreamEngine(socket, protocol, endpoint, args);
} else {
engine = StreamEngineFactory.newStreamEngineWithoutAuth(socket, protocol);
}
} catch (Exception e) {
throw new InvocationTargetException(e, "Failed to instantiate stream engine: " + e);
}
String userName = Subjects.getDisplayName(engine.getSubject());
LOGGER.info("connection created for user {}", userName);
int p = userName.indexOf('@');
if (p > -1) {
userName = p == 0 ? "unknown" : userName.substring(0, p);
}
return newCell(engine, userName);
}
@Override
public void getInfo(PrintWriter pw)
{
pw.println(" Factory : " + getClass());
pw.println(" Encoding : " + protocol);
if (authClass != null) {
pw.println(" Authentication : " + authClass);
}
}
public abstract Cell newCell(StreamEngine engine, String userName)
throws InvocationTargetException;
}