001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.cxfbc.interceptors;
018
019 import java.security.GeneralSecurityException;
020 import java.security.cert.X509Certificate;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Vector;
024
025 import javax.security.auth.Subject;
026
027 import org.apache.cxf.binding.soap.SoapMessage;
028 import org.apache.cxf.interceptor.Fault;
029 import org.apache.cxf.phase.Phase;
030 import org.apache.cxf.ws.security.wss4j.AbstractWSS4JInterceptor;
031 import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor;
032 import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
033 import org.apache.servicemix.common.security.AuthenticationService;
034 import org.apache.ws.security.WSSecurityEngineResult;
035 import org.apache.ws.security.WSUsernameTokenPrincipal;
036 import org.apache.ws.security.handler.WSHandlerConstants;
037 import org.apache.ws.security.handler.WSHandlerResult;
038
039
040 public class JbiJAASInterceptor extends AbstractWSS4JInterceptor {
041
042 private String domain = "servicemix-domain";
043 private AuthenticationService authenticationService;
044 private ThreadLocal<Subject> currentSubject = new ThreadLocal<Subject>();
045 private boolean x509;
046 private boolean delegateToJaas;
047
048
049 public JbiJAASInterceptor(AuthenticationService authenticationService, boolean x509, boolean delegateToJaas) {
050 super();
051 setPhase(Phase.PRE_PROTOCOL);
052 getAfter().add(WSS4JInInterceptor.class.getName());
053 getAfter().add(PolicyBasedWSS4JInInterceptor.class.getName());
054 this.authenticationService = authenticationService;
055 this.x509 = x509;
056 this.delegateToJaas = delegateToJaas;
057 }
058
059
060 public void handleMessage(SoapMessage message) throws Fault {
061
062 try {
063 if (!delegateToJaas) {
064 return;
065 }
066 Subject subject = (Subject) currentSubject.get();
067
068 if (subject == null) {
069 subject = new Subject();
070 currentSubject.set(subject);
071 }
072 List<Object> results = (Vector<Object>)message.get(WSHandlerConstants.RECV_RESULTS);
073 if (results == null) {
074 return;
075 }
076 for (Iterator iter = results.iterator(); iter.hasNext();) {
077 WSHandlerResult hr = (WSHandlerResult) iter.next();
078 if (hr == null || hr.getResults() == null) {
079 return;
080 }
081 boolean authenticated = false;
082
083 //favor WSSE UsernameToken based authentication over X.509 certificate
084 //based authentication. For that purpose we iterate twice over the
085 //WSHandler result list
086 for (Iterator it = hr.getResults().iterator(); it.hasNext();) {
087 WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();
088
089 if (er != null && er.getPrincipal() instanceof WSUsernameTokenPrincipal) {
090 WSUsernameTokenPrincipal p = (WSUsernameTokenPrincipal)er.getPrincipal();
091 subject.getPrincipals().add(p);
092 this.authenticationService.authenticate(subject, domain, p.getName(), p.getPassword());
093 authenticated = true;
094 }
095 }
096
097 //Second iteration checking for X.509 certificate to run authentication on
098 //but only if not already authenticated on WSSE UsernameToken
099 if (!authenticated && x509) {
100 for (Iterator it = hr.getResults().iterator(); it.hasNext();) {
101 WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();
102
103 if (er != null && er.getCertificate() instanceof X509Certificate) {
104 X509Certificate cert = er.getCertificate();
105 this.authenticationService.authenticate(subject, domain, cert.getIssuerX500Principal().getName(), cert);
106 }
107 }
108 }
109 }
110
111 message.put(Subject.class, subject);
112 } catch (GeneralSecurityException e) {
113 throw new Fault(e);
114 } catch (java.lang.reflect.UndeclaredThrowableException e) {
115 java.lang.Throwable undeclared = e.getUndeclaredThrowable();
116 if (undeclared != null
117 && undeclared instanceof java.lang.reflect.InvocationTargetException) {
118 throw new Fault(
119 ((java.lang.reflect.InvocationTargetException) undeclared)
120 .getTargetException());
121 }
122
123 } finally {
124 currentSubject.set(null);
125 }
126 }
127
128 }