/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, 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/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.sip;
import com.ericsson.ssa.container.reporter.ReporterResolver;
import com.ericsson.ssa.container.reporter.Reporter;
import com.ericsson.ssa.container.sim.ServletDispatcher;
import java.io.IOException;
import java.security.Principal;
import javax.servlet.sip.URI;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.sip.SipServletResponse;
import org.jvnet.glassfish.comms.security.auth.impl.SipSecurityManager;
import org.jvnet.glassfish.comms.util.LogUtil;
/**
*
* @author k.venugopal@sun.com
*/
public class SecurityInterceptor implements Layer {
private Logger m_logger = LogUtil.SIP_LOGGER.getLogger();
private Layer _nextLayer = null;
private Reporter _reporter;
private static SecurityInterceptor layer;
private SecurityInterceptor() {
}
public synchronized static SecurityInterceptor getInstance() {
if (layer == null) {
layer = new SecurityInterceptor();
}
return layer;
}
public void next(SipServletRequestImpl req) {
AuthModule authModule = null;
if (req.isInitial()) {
req.pushApplicationDispatcher(this);
} else {
SipApplicationSessionImpl sas = req.getApplicationSessionImpl();
ServletDispatcher sd = sas.getServletDispatcher();
String servletToInvoke = req.getSessionImpl().getHandler();
authModule = sd.getAuthModule();
try {
if (!verifyRequest(req, authModule, servletToInvoke)) {
return;
}
} catch (IOException ex) {
m_logger.log(Level.SEVERE, null, ex);
return;
}
}
// Send onwards
LayerHelper.next(req, this, _nextLayer);
}
public boolean verifyRequest(SipServletRequestImpl req) {
SipApplicationSessionImpl sas = req.getApplicationSessionImpl();
ServletDispatcher sd = sas.getServletDispatcher();
String servletToInvoke = req.getSessionImpl().getHandler();
AuthModule authModule = sd.getAuthModule();
try {
if (!verifyRequest(req, authModule, servletToInvoke)) {
return false;
}
} catch (IOException ex) {
m_logger.log(Level.SEVERE, null, ex);
return false;
}
return true;
}
void sendErrorResponse(SipServletRequestImpl request, AuthModule authModule, String servletName) throws IOException {
SipServletResponse resp = authModule.createErrorResponse(request, servletName);
resp.send();
}
private void sendErrorResponse(SipServletRequestImpl request, int statusCode, String msg) throws IOException {
SipServletResponse resp = request.createResponse(statusCode);
if (msg != null) {
resp.setStatus(statusCode, msg);
resp.addHeader("Error-Info", msg);
}
resp.send();
}
private void sendRedirect(SipServletRequestImpl request) throws IOException {
URI uriValue = request.getRequestURI();
String uri = uriValue.toString();
String port = null;
try {
port = AuthModule.getTLSPort();
} catch (com.sun.enterprise.config.ConfigException ce) {
ce.printStackTrace();
}
if (!uri.contains("sips") && port != null && port.length() > 0) {
uri = uri.replaceFirst("sip:", "sips:");
int index = uri.indexOf(":", "sips:".length());
if (index != -1) {
uri = (String) uri.subSequence(0, index);
}
uri = uri + ":" + port;
}
SipServletResponse resp = request.createResponse(302);
resp.setHeader("Contact", uri);
resp.send();
}
public void next(SipServletResponseImpl resp) {
LayerHelper.next(resp, this, _nextLayer);
}
public void registerNext(Layer layer) {
_nextLayer = layer;
}
public void setReporters(String reporters) {
_reporter = ReporterResolver.getInstance().getReporter(reporters);
}
public Reporter getReporter() {
return this._reporter;
}
public void dispatch(SipServletRequestImpl req) {
req.popDispatcher().dispatch(req);
}
public void dispatch(SipServletResponseImpl resp) {
resp.popDispatcher().dispatch(resp);
}
public boolean verifyRequest(SipServletRequestImpl req, AuthModule authModule, String servletToInvoke) throws IOException {
SipSecurityManager.setSecurityContext(null);
if (!authModule.hasUserDataPermissions(servletToInvoke, req.getMethod(), req.isSecure())) {
sendRedirect(req);
return false;
}
boolean permissionGranted = authModule.hasResourcePermissions(req.getMethod(), servletToInvoke);
if (!permissionGranted) {
if ((req.getUserPrincipal() == null) &&
authModule.needsAuthentication(servletToInvoke,
req.getMethod())) {
if (!authenticate(req, authModule, servletToInvoke)) {
return false;
}
if (!authModule.checkServletConstraints(req,
servletToInvoke)) {
sendErrorResponse(req, 403, null);
return false;
}
} else if (authModule.needsAuthentication(servletToInvoke,
req.getMethod())) {
Principal principal = req.getUserPrincipal();
SipSecurityManager.setSecurityContext(principal);
if (!authModule.checkServletConstraints(req,
servletToInvoke)) {
//sendErrorResponse(req, 403, null);
req.setUserPrincipal(null);
if (authenticate(req, authModule, servletToInvoke)) {
if (!authModule.checkServletConstraints(req,
servletToInvoke)) {
sendErrorResponse(req, 403, null);
return false;
}
} else {
return false;
}
}
}
}
return true;
}
private boolean authenticate(SipServletRequestImpl req, AuthModule authModule, String servletToInvoke) throws IOException {
try {
authModule.authenticate(req, servletToInvoke);
} catch (SecurityException se) {
m_logger.log(Level.FINE, se.getMessage());
sendErrorResponse(req, 400, se.getMessage());
return false;
}
if (req.getUserPrincipal() == null) {
if (!(req.getMethod().equals("ACK") || req.getMethod().equals("CANCEL"))) {
//sendErrorResponse(req, authModule, servletToInvoke);
return false;
}
}
return true;
}
// private void testRFC4474(SipServletRequestImpl req) {
// try {
// RFC4474Processor rp = new RFC4474Processor();
// String k = "/media/externalhd/internet/newident/key.der";//atlanta.privkey
// File f = new File(k);
// FileInputStream fis = new FileInputStream(f);
// byte[] bb = new byte[635];
// fis = new FileInputStream(k);
// int len = fis.read(bb);
// String pk = "/media/externalhd/internet/newident/atlanta.cer";//atlanta.privkey
//
// PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bb);
// // X509EncodedKeySpec ks = new X509EncodedKeySpec(bb) ;
// KeyFactory kf = KeyFactory.getInstance("RSA");
// PrivateKey key = kf.generatePrivate(ks);
// rp.sign(req, key, AlgorithmSuite.RSASHA1, "https://129.158.229.100:8181/atlanta.cer");
// fis = new FileInputStream(new File(pk));
//
//
// CertificateFactory cf = CertificateFactory.getInstance("X.509");
// X509Certificate x509Cert = (X509Certificate) cf.generateCertificate(fis);
//
//
// PublicKey pkey = x509Cert.getPublicKey();
// rp.verify(req);
// ;
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// }
}