/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.ejb.plugins; import java.security.Principal; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLPeerUnverifiedException; import java.security.cert.X509Certificate; import java.util.Set; import org.jboss.invocation.Invocation; import org.jboss.security.ssl.DomainServerSocketFactory; import org.jboss.security.CertificatePrincipal; import org.jboss.security.SecurityContext; import org.jboss.security.auth.certs.SubjectDNMapping; import org.jboss.security.identity.Identity; import org.jboss.security.identity.IdentityFactory; import org.jboss.security.identity.IdentityType; import org.jboss.security.identity.extensions.CertificateIdentity; import org.jboss.security.identity.extensions.CertificateIdentityFactory; import org.jboss.security.identity.extensions.CredentialIdentity; /** * An interceptor that looks for the peer certificates from the SSLSession * associated with the sessionIDKey(defaults to SESSION_ID) of the invocation. * * @see org.jboss.security.ssl.DomainServerSocketFactory * * @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>. * @version $Revision: 81030 $ */ public class SSLSessionInterceptor extends AbstractInterceptor { /** The certificate to principal mapping interface */ private CertificatePrincipal cpMapping = new SubjectDNMapping(); /** The name of the invocation key with the session id */ private String sessionIDKey = "SESSION_ID"; public Object invokeHome(Invocation mi) throws Exception { extractSessionPrincipal(mi); Object returnValue = getNext().invokeHome(mi); return returnValue; } public CertificatePrincipal getPrincialMapping() { return cpMapping; } public void setPrincialMapping(CertificatePrincipal cpMapping) { this.cpMapping = cpMapping; } public String getSessionIDKey() { return sessionIDKey; } public void setSessionIDKey(String sessionIDKey) { this.sessionIDKey = sessionIDKey; } public Object invoke(Invocation mi) throws Exception { extractSessionPrincipal(mi); Object returnValue = getNext().invoke(mi); return returnValue; } /** * Look for the session id in the invocation and if there is an associated * session in DomainServerSocketFactory, use the client cert as the * credential, and the cert principal mapping as the principal. * * @param mi - the method invocation * @throws SSLPeerUnverifiedException */ private void extractSessionPrincipal(Invocation mi) throws SSLPeerUnverifiedException { String sessionID = (String) mi.getValue(sessionIDKey); if( sessionID != null ) { SSLSession session = DomainServerSocketFactory.getSSLSession(sessionID); if( session != null ) { X509Certificate[] certs = (X509Certificate[]) session.getPeerCertificates(); Principal caller = cpMapping.toPrinicipal(certs); mi.setPrincipal(caller); mi.setCredential(certs); //Update the invocation security context SecurityContext invSC = mi.getSecurityContext(); if(invSC != null) { CertificateIdentityFactory identityFactory = (CertificateIdentityFactory) IdentityFactory.getFactory(IdentityType.CERTIFICATE); CertificateIdentity certIdentity = identityFactory.createIdentity(caller, certs, null); invSC.getUtil().clearIdentities(CredentialIdentity.class); invSC.getUtil().addIdentity(certIdentity); } } } } }