/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the license at
* https://glassfish.dev.java.net/public/CDDLv1.0.html or
* glassfish/bootstrap/legal/CDDLv1.0.txt.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at glassfish/bootstrap/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* you own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright (c) Ericsson AB, 2004-2007. All rights reserved.
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
*/
package org.jvnet.glassfish.comms.security.auth.impl;
import com.sun.enterprise.config.serverbeans.ElementProperty;
import com.sun.enterprise.config.serverbeans.IdentityAssertionTrust;
import com.sun.enterprise.config.serverbeans.TrustedEntity;
import com.sun.enterprise.security.AppservAccessController;
import com.sun.enterprise.security.SecurityContext;
import com.sun.enterprise.security.auth.LoginContextDriver;
import com.sun.enterprise.security.auth.PrincipalMapper;
import com.sun.enterprise.security.auth.TrustHandler;
import com.sun.enterprise.security.auth.login.AssertedCredentials;
import com.sun.web.security.PrincipalGroupFactory;
import com.sun.web.security.WebPrincipal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.LoginException;
import static org.jvnet.glassfish.comms.security.util.Constants.securityLogger;
import javax.security.auth.Subject;
import javax.servlet.sip.SipServletRequest;
/**
*
* @author K.Venugopal@sun.com
*/
public class PAssertedAuthenticator extends Authenticator {
public static final String INTERMEDIATE = "intermediate";
public static final String DESTINATION = "destination";
public static final String PRIVACY = "Privacy";
public static final String P_ASSERTED_IDENTITY = "P-Asserted-Identity";
public static final String P_PREFERRED_IDENTITY = "P-Preferred-Identity";
private String realmName = null;
private TrustHandler handler = null;
private PrincipalMapper mapper = null;
private String handlerClass = null;
private HashMap<String, Map> trustMap = null;
private Vector<String> inIpList = new Vector<String>();
private Vector<String> outIpList = new Vector<String>();
public PAssertedAuthenticator(IdentityAssertionTrust trustConfig) {
initialize(trustConfig);
}
public Principal authenticate(SipServletRequest request) {
throw new UnsupportedOperationException();
}
public Principal authenticate(SipServletRequest request, String host, String realmName, String messagedirection) {
this.realmName = realmName;
ListIterator passertedHeader = request.getHeaders(P_ASSERTED_IDENTITY);
final String id = request.getHeader(PRIVACY);
ArrayList<String> arrayList = new ArrayList<String>();
while (passertedHeader.hasNext()) {
arrayList.add((String) passertedHeader.next());
}
if (arrayList.size() == 0) {
return null;
}
boolean isTrusted = false;
final String[] pAssrtValues = arrayList.toArray(new String[0]);
Principal[] principals = new Principal[arrayList.size()];
for (int i = 0; i < arrayList.size(); i++) {
principals[i] = PrincipalGroupFactory.getPrincipalInstance(pAssrtValues[i],
realmName);
}
final Principal[] mappedPrincipals = this.mapUsers(principals);
if (this.isTrusted(principals, host, messagedirection)) {
final AssertedPrincipalInfo ap = new AssertedPrincipalInfo(mappedPrincipals[0].getName(), pAssrtValues, id, true);
final AssertedCredentials creds = new AssertedCredentials(realmName,
mappedPrincipals[0].getName(), ap);
Principal p = (Principal) AppservAccessController.doPrivileged(new PrivilegedAction() {
public java.lang.Object run() {
try {
LoginContextDriver.login(creds);
SecurityContext secCtx = SecurityContext.getCurrent();
secCtx.getSubject().getPrivateCredentials().add(ap);
return new WebPrincipal(creds.getUserName(), null, secCtx);
} catch (LoginException ex) {
securityLogger.log(Level.SEVERE, "P-Asserted Authentication failed", ex);
throw new SecurityException("P-Asserted Authentication failed");
}
}
});
if(p != null){
return p;
}
}
AppservAccessController.doPrivileged(new PrivilegedAction() {
public java.lang.Object run() {
AssertedPrincipalInfo ap = new AssertedPrincipalInfo(mappedPrincipals[0].getName(), pAssrtValues, id, false);
Subject sub = new Subject();
SecurityContext securityContext = new SecurityContext(sub);
SecurityContext.setCurrent(securityContext);
sub.getPrivateCredentials().add(ap);
return null;
}
});
return null;
}
public boolean isTrusted(Principal[] pv, String host, String messagedirection) {
boolean result = false;
if (this.handler != null) {
return handler.isTrusted(host, messagedirection, null, pv);
} else {
if (messagedirection == INTERMEDIATE) {
if (inIpList.contains(host)) {
//throw new SecurityException("P-Asserted Authentication failed");
result = true;
}
} else {
if (outIpList.contains(host)) {
result = true;
}
}
}
return result;
}
public void verifyMessage(SipServletRequest req, String remoteAddrss) {
ListIterator passertedHeader = req.getHeaders(P_ASSERTED_IDENTITY);
String id = req.getHeader(PRIVACY);
SecurityContext sc = SecurityContext.getCurrent();
Subject subject = sc.getSubject();
if (sc != null && subject != null) {
Set<Object> creds = subject.getPrivateCredentials();
Iterator<Object> iterator = creds.iterator();
AssertedPrincipalInfo authInfo = null;
while (iterator.hasNext()) {
Object obj = iterator.next();
if (obj instanceof AssertedPrincipalInfo) {
authInfo = (AssertedPrincipalInfo) obj;
break;
}
}
if (authInfo != null && !authInfo.isTrusted()) {
//we got this from a remote host we don't trust.
//don't forward the headers in this request.
req.removeHeader(P_ASSERTED_IDENTITY);
req.removeHeader(P_PREFERRED_IDENTITY);
return;
}
}
if (id == null || id.length() == 0) {
return;
}
//destination host is not trusted
//don't forward the headers to the destination.
if (!isTrusted(null, remoteAddrss, DESTINATION)) {
req.removeHeader(P_ASSERTED_IDENTITY);
req.removeHeader(P_PREFERRED_IDENTITY);
}
}
private Principal[] mapUsers(Principal[] principals) {
if (mapper == null) {
TrustHandlerImpl th = new TrustHandlerImpl();
return th.mapIdentity(principals);
}
return mapper.mapIdentity(principals);
}
private void initialize(IdentityAssertionTrust trustConfig) {
try {
com.sun.enterprise.config.serverbeans.TrustHandler th = trustConfig.getTrustHandler();
if (trustConfig.getTrustedEntity() != null) {
processStaticValues(trustConfig);
}
if (th != null) {
String hc = th.getClassName();
ElementProperty[] epList = th.getElementProperty();
Properties props = new Properties();
if (epList != null) {
for (int i = 0; i < epList.length; i++) {
ElementProperty ep = epList[i];
String name = ep.getName();
String value = ep.getValue();
props.setProperty(name, value);
}
}
if (hc != null) {
Class trustClass = Class.forName(hc);
handler = (TrustHandler) trustClass.newInstance();
}
handler.initialize(props);
}
} catch (InstantiationException ex) {
securityLogger.log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
securityLogger.log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
securityLogger.log(Level.SEVERE, null, ex);
}
}
private void processStaticValues(IdentityAssertionTrust iat) {
TrustedEntity[] etList = iat.getTrustedEntity();
for (int i = 0; i < etList.length; i++) {
TrustedEntity et = etList[i];
String messageDirection = et.getTrustedAs();
String ip = et.getIpAddress();
String hostName = et.getHostName();
String hostToIP = "";
addToList(ip, messageDirection);
if (hostName != null && hostName.length() > 0) {
hostToIP = getIPAddress(hostName);
addToList(hostToIP, messageDirection);
}
}
}
private void addToList(String ip, String messageDirection) {
if (ip == null || ip.length() == 0) {
return;
}
if (messageDirection == null) {
outIpList.add(ip);
inIpList.add(ip);
return;
}
if (messageDirection.equals("intermediate")) {
inIpList.add(ip);
} else if (messageDirection.equals("destination")) {
outIpList.add(ip);
} else {
outIpList.add(ip);
inIpList.add(ip);
}
}
private String getIPAddress(String hostName) {
String ipAddr = "";
try {
InetAddress addr = InetAddress.getByName(hostName);
byte[] address = addr.getAddress();
for (int i = 0; i < address.length; i++) {
if (i > 0) {
ipAddr += ".";
}
ipAddr += address[i] & 0xFF;
}
} catch (UnknownHostException ex) {
securityLogger.log(Level.SEVERE, null, ex);
}
return ipAddr;
}
}