1 package org.zxid; 2 3 /* zxidsrvlet.java - SAML SSO Java/Tomcat servlet script that calls libzxid using JNI 4 * Copyright (c) 2007-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved. 5 * Author: Sampo Kellomaki (sampo@iki.fi) 6 * This is confidential unpublished proprietary source code of the author. 7 * NO WARRANTY, not even implied warranties. Contains trade secrets. 8 * Distribution prohibited unless authorized in writing. 9 * Licensed under Apache License 2.0, see file COPYING. 10 * $Id: zxidsrvlet.java,v 1.3 2009-11-20 20:27:13 sampo Exp $ 11 * 12.1.2007, created --Sampo 12 * 16.10.2009, refined from zxidhlo example to truly useful servlet that populates session --Sampo 13 * 14 * See also: README-zxid section 10 "zxid_simple() API" 15 */ 16 17 /* 18 * 8.10.2010 , Modified slightly by Stijn Lievens to avoid having to compile 19 * in the configuration string. 20 * Updated to conform (better) to Java conventions. 21 * Removed use of deprecated methods. 22 */ 23 24 import java.io.IOException; 25 import java.net.URLDecoder; 26 27 import javax.servlet.ServletConfig; 28 import javax.servlet.ServletException; 29 import javax.servlet.http.Cookie; 30 import javax.servlet.http.HttpServlet; 31 import javax.servlet.http.HttpServletRequest; 32 import javax.servlet.http.HttpServletResponse; 33 import javax.servlet.http.HttpSession; 34 35 import zxidjava.zxidjni; 36 37 public class ZxidServlet extends HttpServlet { 38 39 40 private static final long serialVersionUID = 1L; 41 42 /** 43 * The ZXID configuration String. 44 */ 45 // Maybe this one can be removed. 46 private String conf; // e.g. "URL=http://zxid-sp.tas3.kent.ac.uk:8080/zxid/sso&PATH=/var/zxid/"; 47 48 /** 49 * The ZXID configuration object. 50 */ 51 private zxidjava.zxid_conf cf; 52 53 /** 54 * Load the ZXID native library. 55 */ 56 static { 57 System.loadLibrary("zxidjni"); 58 } 59 60 /** 61 * Does the actual calling of the ZXID native code through {@code zxidjni.simple_cf}. 62 * 63 * @param req 64 * @param res 65 * @param qs 66 * @throws ServletException 67 * @throws IOException 68 */ doZxid(HttpServletRequest req, HttpServletResponse res, String qs)69 private void doZxid(HttpServletRequest req, HttpServletResponse res, String qs) 70 throws ServletException, IOException { 71 if (req.getParameter("gr") != null || req.getParameter("gl") != null) { 72 req.getSession(true).invalidate(); // Invalidate local ses in case of SLO 73 } 74 String ret = zxidjni.simple_cf(cf, -1, qs, null, 0x3d54); // QS response 75 // requested 76 System.err.println(ret); 77 switch (ret.charAt(0)) { 78 case 'L': /* Redirect: ret == "LOCATION: urlCRLF2" */ 79 res.sendRedirect(ret.substring(10, ret.length() - 4)); 80 return; 81 case '<': 82 switch (ret.charAt(1)) { 83 case 's': /* <se: SOAP envelope */ 84 case 'm': /* <m20: metadata */ 85 res.setContentType("text/xml"); 86 break; 87 default: 88 res.setContentType("text/html"); 89 break; 90 } 91 res.setContentLength(ret.length()); 92 res.getOutputStream().print(ret); 93 break; 94 case 'z': /* Authorization denied case (if PDP_URL was configured) */ 95 System.err.println("Deny (z)"); 96 res.sendError(403, "Denied. Authorization to rs(" + req.getParameter("RelayState") 97 + ") was refused by a PDP."); 98 return; 99 case 'd': /* Logged in case (both LDIF and QS will start by "dn") */ 100 HttpSession ses = req.getSession(true); 101 String[] avs = ret.split("&"); 102 for (int i = 0; i < avs.length; ++i) { 103 String[] av = avs[i].split("="); 104 ses.setAttribute(av[0], URLDecoder.decode(av.length > 1 ? av[1] : "", "UTF-8")); 105 } 106 107 /* 108 * Make sure cookie is visible to other servlets on the same server. 109 * Alternately you could add emptySessionPath="true" to tomcat 110 * conf/server.xml 111 */ 112 Cookie[] cookies = req.getCookies(); 113 if (cookies != null) { 114 for (int i = 0; i < cookies.length; i++) { 115 if (cookies[i].getName().equals("JSESSIONID")) { // MUST match cookie 116 // name 117 cookies[i].setPath("/"); 118 break; 119 } 120 } 121 } 122 123 System.err.println("Logged in. jses(" + ses.getId() + ") rs(" + ses.getAttribute("rs") + ")"); 124 String rs = URLDecoder.decode(ses.getAttribute("rs").toString(), "UTF-8"); 125 if (rs != null && rs.length() > 0 && rs.charAt(rs.length() - 1) != '-') { 126 res.sendRedirect(rs); 127 } 128 129 /* Redirect was not viable. Just show the management screen. */ 130 131 ret = zxidjni.fed_mgmt_cf(cf, null, -1, ses.getAttribute("sesid").toString(), 0x3d54); 132 res.setContentType("text/html"); 133 res.setContentLength(ret.length()); 134 res.getOutputStream().print(ret); 135 break; 136 default: 137 System.err.println("Unknown zxid_simple() response(" + ret + ")."); 138 } 139 } 140 141 //@Override doGet(HttpServletRequest req, HttpServletResponse res)142 public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, 143 IOException { 144 System.err.print("Start GET...\n"); 145 // LECP/ECP PAOS header checks 146 doZxid(req, res, req.getQueryString()); 147 } 148 149 //@Override doPost(HttpServletRequest req, HttpServletResponse res)150 public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, 151 IOException { 152 System.err.println("Start POST..."); 153 int len = req.getContentLength(); 154 byte[] b = new byte[len]; 155 int here, got; 156 for (here = 0; here < len; here += got) { 157 got = req.getInputStream().read(b, here, len - here); 158 } 159 String qs = new String(b, 0, len); 160 doZxid(req, res, qs); 161 } 162 163 //@Override init(ServletConfig config)164 public void init(ServletConfig config) throws ServletException { 165 if (config.getInitParameter("zxid-configuration") != null) { 166 System.err.println("The zxid-configuration parameter is:" 167 + config.getInitParameter("zxid-configuration")); 168 conf = config.getInitParameter("zxid-configuration"); 169 } 170 cf = zxidjni.new_conf_to_cf(conf); 171 } 172 } 173