package org.dcache.xrootd.door; import io.netty.channel.ChannelHandlerContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.Subject; import java.net.InetAddress; import java.net.InetSocketAddress; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.HashSet; import java.util.Set; import diskCacheV111.util.CacheException; import diskCacheV111.util.PermissionDeniedCacheException; import org.dcache.auth.LoginReply; import org.dcache.auth.LoginStrategy; import org.dcache.auth.Origin; import org.dcache.util.CertificateFactories; import org.dcache.xrootd.core.XrootdAuthenticationHandler; import org.dcache.xrootd.core.XrootdException; import org.dcache.xrootd.plugins.AuthenticationFactory; import static java.util.Arrays.asList; import static org.dcache.xrootd.protocol.XrootdProtocol.kXR_NotAuthorized; import static org.dcache.xrootd.protocol.XrootdProtocol.kXR_ServerError; /** * An XrootdAuthenticationHandler which after successful * authentication delegates login to a LoginStrategy. * * Generates a LoginEvent after successful login. */ public class LoginAuthenticationHandler extends XrootdAuthenticationHandler { private static final Logger _log = LoggerFactory.getLogger(LoginAuthenticationHandler.class); private LoginStrategy _loginStrategy; private CertificateFactory _cf; public LoginAuthenticationHandler(AuthenticationFactory authenticationFactory, LoginStrategy loginStrategy) { super(authenticationFactory); _loginStrategy = loginStrategy; _cf = CertificateFactories.newX509CertificateFactory(); } @Override protected Subject login(ChannelHandlerContext context, Subject subject) throws XrootdException { try { subject = addOrigin(subject, ((InetSocketAddress) context.channel().remoteAddress()).getAddress()); LoginReply reply = _loginStrategy.login(translateSubject(subject)); context.fireUserEventTriggered(new LoginEvent(reply)); return reply.getSubject(); } catch (PermissionDeniedCacheException e) { _log.warn("Authorization denied for {}: {}", subject, e.getMessage()); throw new XrootdException(kXR_NotAuthorized, e.getMessage()); } catch (CacheException | CertificateException e) { _log.error("Authorization failed for {}: {}", subject, e.getMessage()); throw new XrootdException(kXR_ServerError, e.getMessage()); } } private Subject addOrigin(Subject subject, InetAddress address) { Subject newSubject; if (subject == null) { newSubject = new Subject(); } else { newSubject = new Subject(false, subject.getPrincipals(), subject.getPublicCredentials(), subject.getPrivateCredentials()); } newSubject.getPrincipals().add(new Origin(address)); return newSubject; } private Subject translateSubject(Subject subject) throws CertificateException { if (subject == null) { return null; } Set<Object> publicCredentials = new HashSet<>(); for (Object credential : subject.getPublicCredentials()) { if (credential instanceof X509Certificate[]) { publicCredentials.add(_cf.generateCertPath(asList((X509Certificate[]) credential))); } else { publicCredentials.add(credential); } } return new Subject(false, subject.getPrincipals(), publicCredentials, subject.getPrivateCredentials()); } }