ClientCertAuthHandler.java 10.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.keystore.KeyStoreService
 *  com.day.crx.security.token.TokenUtil
 *  javax.jcr.RepositoryException
 *  javax.servlet.http.HttpServletRequest
 *  javax.servlet.http.HttpServletResponse
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.jackrabbit.api.security.user.Authorizable
 *  org.apache.jackrabbit.api.security.user.UserManager
 *  org.apache.sling.api.resource.LoginException
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ResourceResolverFactory
 *  org.apache.sling.auth.core.spi.AuthenticationHandler
 *  org.apache.sling.auth.core.spi.AuthenticationInfo
 *  org.apache.sling.jcr.api.SlingRepository
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.auth.cert.impl;

import com.adobe.granite.auth.cert.UserCertificateMapping;
import com.adobe.granite.auth.cert.UserCertificateMappingException;
import com.adobe.granite.keystore.KeyStoreService;
import com.day.crx.security.token.TokenUtil;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.RepositoryException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.auth.core.spi.AuthenticationHandler;
import org.apache.sling.auth.core.spi.AuthenticationInfo;
import org.apache.sling.jcr.api.SlingRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(specVersion="1.1", label="%auth.clientcerthandler.name", description="%auth.clientcerthandler.description", metatype=1)
@Service
@Properties(value={@Property(name="path", value={"/"}), @Property(name="service.ranking", intValue={0}, propertyPrivate=0)})
public class ClientCertAuthHandler
implements AuthenticationHandler,
UserCertificateMapping {
    private final Logger log;
    @Property(name="service.description")
    private static final String DESCRIPTION = "Granite Client Certificate Authentication Handler";
    @Property(name="authtype", propertyPrivate=1)
    public static final String CERT_AUTHENTICATED = "certAuthenticated";
    public static final String CERT = "cert";
    public static final String SEPARATOR = "#";
    @Reference
    private SlingRepository repository;
    @Reference
    private ResourceResolverFactory rrf;
    @Reference
    private KeyStoreService keyStoreService;

    public ClientCertAuthHandler() {
        this.log = LoggerFactory.getLogger((String)this.getClass().getName());
    }

    public AuthenticationInfo extractCredentials(HttpServletRequest request, HttpServletResponse response) {
        X509Certificate[] certs = (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
        AuthenticationInfo authInfo = null;
        if (certs != null && certs.length > 0) {
            String mappedUser = null;
            X509Certificate cert = certs[0];
            try {
                mappedUser = this.findMappedUsers(cert);
                if (mappedUser != null) {
                    authInfo = TokenUtil.createCredentials((HttpServletRequest)request, (HttpServletResponse)response, (SlingRepository)this.repository, (String)mappedUser, (boolean)true);
                    authInfo.put("cert", (Object)cert);
                }
            }
            catch (Exception e) {
                this.log.warn("Unable to create token credentials, setting cert for uid " + mappedUser, (Throwable)e);
                authInfo = new AuthenticationInfo("certAuthenticated", mappedUser);
                authInfo.put("cert", (Object)cert);
            }
        }
        return authInfo;
    }

    private String findMappedUsers(X509Certificate cert) throws UserCertificateMappingException {
        String user;
        user = null;
        ResourceResolver servicesResolver = null;
        try {
            int index;
            servicesResolver = this.rrf.getServiceResourceResolver(null);
            KeyStore trustStore = this.keyStoreService.getTrustStore(servicesResolver);
            String alias = trustStore.getCertificateAlias(cert);
            if (alias != null && (index = alias.lastIndexOf("#")) > -1) {
                user = alias.substring(0, index);
            }
        }
        catch (LoginException e) {
            throw new UserCertificateMappingException((Throwable)e);
        }
        catch (KeyStoreException e) {
            throw new UserCertificateMappingException(e);
        }
        finally {
            if (servicesResolver != null) {
                servicesResolver.close();
            }
        }
        return user;
    }

    public boolean requestCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {
        return false;
    }

    public void dropCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {
    }

    @Override
    public void mapCertificate(ResourceResolver resolver, String userId, X509Certificate certificate) throws UserCertificateMappingException {
        block6 : {
            String alias = userId + "#" + System.currentTimeMillis();
            try {
                UserManager userManager = (UserManager)resolver.adaptTo(UserManager.class);
                if (userManager != null) {
                    Authorizable user = userManager.getAuthorizable(userId);
                    if (user != null && !user.isGroup()) {
                        KeyStore trustStore = this.keyStoreService.getTrustStore(resolver);
                        String oldAlias = trustStore.getCertificateAlias(certificate);
                        if (oldAlias != null) {
                            trustStore.deleteEntry(oldAlias);
                        }
                        trustStore.setCertificateEntry(alias, certificate);
                        break block6;
                    }
                    throw new UserCertificateMappingException("Failed to obtain a user using given userId " + userId);
                }
                throw new UserCertificateMappingException("Failed to adapt given resolver to a user manager.");
            }
            catch (RepositoryException e) {
                throw new UserCertificateMappingException((Throwable)e);
            }
            catch (KeyStoreException e) {
                throw new UserCertificateMappingException(e);
            }
        }
    }

    @Override
    public void unmapCertificate(ResourceResolver resolver, String alias) throws UserCertificateMappingException {
        block3 : {
            try {
                KeyStore trustStore = this.keyStoreService.getTrustStore(resolver);
                if (trustStore.containsAlias(alias)) {
                    trustStore.deleteEntry(alias);
                    break block3;
                }
                throw new UserCertificateMappingException("Alias " + alias + " doesn't exist.");
            }
            catch (KeyStoreException e) {
                throw new UserCertificateMappingException(e);
            }
        }
    }

    @Override
    public Map<String, X509Certificate> listCertificates(ResourceResolver resolver, String userId) throws UserCertificateMappingException {
        HashMap<String, X509Certificate> certificatesMap;
        block6 : {
            certificatesMap = null;
            try {
                UserManager userManager = (UserManager)resolver.adaptTo(UserManager.class);
                if (userManager != null) {
                    Authorizable user = userManager.getAuthorizable(userId);
                    if (user != null && !user.isGroup()) {
                        KeyStore trustStore = this.keyStoreService.getTrustStore(resolver);
                        certificatesMap = new HashMap<String, X509Certificate>();
                        Enumeration<String> aliases = trustStore.aliases();
                        while (aliases.hasMoreElements()) {
                            String alias = aliases.nextElement();
                            if (!alias.startsWith(userId + "#")) continue;
                            certificatesMap.put(alias, (X509Certificate)trustStore.getCertificate(alias));
                        }
                        break block6;
                    }
                    throw new UserCertificateMappingException("Failed to obtain a user using given userId " + userId);
                }
                throw new UserCertificateMappingException("Failed to adapt given resolver to a user manager.");
            }
            catch (RepositoryException e) {
                throw new UserCertificateMappingException((Throwable)e);
            }
            catch (KeyStoreException e) {
                throw new UserCertificateMappingException(e);
            }
        }
        return certificatesMap;
    }

    protected void bindRepository(SlingRepository slingRepository) {
        this.repository = slingRepository;
    }

    protected void unbindRepository(SlingRepository slingRepository) {
        if (this.repository == slingRepository) {
            this.repository = null;
        }
    }

    protected void bindRrf(ResourceResolverFactory resourceResolverFactory) {
        this.rrf = resourceResolverFactory;
    }

    protected void unbindRrf(ResourceResolverFactory resourceResolverFactory) {
        if (this.rrf == resourceResolverFactory) {
            this.rrf = null;
        }
    }

    protected void bindKeyStoreService(KeyStoreService keyStoreService) {
        this.keyStoreService = keyStoreService;
    }

    protected void unbindKeyStoreService(KeyStoreService keyStoreService) {
        if (this.keyStoreService == keyStoreService) {
            this.keyStoreService = null;
        }
    }
}