package org.dcache.webdav; import org.springframework.beans.factory.annotation.Required; import javax.security.auth.Subject; import java.security.Principal; import java.util.Set; import diskCacheV111.util.CacheException; import org.dcache.auth.LoginNamePrincipal; import org.dcache.auth.LoginReply; import org.dcache.auth.LoginStrategy; import org.dcache.auth.PasswordCredential; import org.dcache.auth.Subjects; import org.dcache.auth.UnionLoginStrategy.AccessLevel; import org.dcache.auth.attributes.LoginAttribute; import org.dcache.auth.attributes.Restrictions; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static java.util.Objects.requireNonNull; import static org.dcache.auth.UnionLoginStrategy.AccessLevel.READONLY; import static org.dcache.auth.UnionLoginStrategy.AccessLevel.NONE; /** * Add support for logging in a particular user as Users.NOBODY, all other * requests are passed on to some wrapped LoginStrategy. If AccessLevel is NONE * then all requests are passed onto the wrapped LoginStrategy. */ public class AnonymousUserLoginStrategy implements LoginStrategy { private LoginStrategy _inner; private String _username; private AccessLevel _anonymousAccess = NONE; public void setAnonymousAccess(AccessLevel level) { _anonymousAccess = requireNonNull(level); } public AccessLevel getAnonymousAccess() { return _anonymousAccess; } @Required public void setNonAnonymousStrategy(LoginStrategy strategy) { _inner = requireNonNull(strategy); } @Required public void setUsername(String username) { _username = requireNonNull(username); } private boolean isAnonymousUser(Subject subject) { return subject.getPrivateCredentials().stream() .filter(PasswordCredential.class::isInstance) .map(PasswordCredential.class::cast) .anyMatch(p -> _username.equals(p.getUsername())) || subject.getPrincipals().stream() .filter(LoginNamePrincipal.class::isInstance) .anyMatch(p -> _username.equals(p.getName())); } @Override public LoginReply login(Subject subject) throws CacheException { if (_anonymousAccess != NONE && isAnonymousUser(subject)) { Set<LoginAttribute> attributes = _anonymousAccess == READONLY ? singleton(Restrictions.readOnly()) : emptySet(); return new LoginReply(Subjects.NOBODY, attributes); } return _inner.login(subject); } @Override public Principal map(Principal principal) throws CacheException { return _inner.map(principal); } @Override public Set<Principal> reverseMap(Principal principal) throws CacheException { return _inner.reverseMap(principal); } }