1 /* zxidwspdemo.java  -  Demonstrate server side of handling a web service call (middle)
2  * Copyright (c) 2012-2016 Synergetics (sampo@synergetics.be), All Rights Reserved.
3  * Copyright (c) 2010-2011 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
4  * Copyright (c) 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: zxidappdemo.java,v 1.3 2009-11-20 20:27:13 sampo Exp $
11  * 16.10.2009, created --Sampo
12  * 16.2.2010, fixed virtual hosting --Sampo
13  * 7.2.2012,  new virtual hosting with <init-param> supplied config --Sampo
14  * 19.2.2016, improved visualization of the Az steps --Sampo
15  *
16  * See also: zxid-java.pd, zxidappdemo.java for client side
17  *
18  * Discovery registration:
19  *   ./zxcot -e http://sp.tas3.pt:8080/zxidservlet/wspdemo 'TAS3 WSP Demo' http://sp.tas3.pt:8080/zxidservlet/wspdemo?o=B urn:x-foobar | ./zxcot -d -b /var/zxid/idpdimd
20  *   touch /var/zxid/idpuid/.all/.bs/urn_x-foobar,l9O3xlWWi9kLZm-yQYRytpf0lqw
21  */
22 
23 import zxidjava.*;   // Pull in the zxidjni.az() API
24 import java.io.*;
25 import javax.servlet.*;
26 import javax.servlet.http.*;
27 
28 public class zxidwspdemo extends HttpServlet {
29     static zxidjava.zxid_conf cf;
30     static { System.loadLibrary("zxidjni"); }
31 
init_zxid_vhost(HttpServletRequest req)32     public void init_zxid_vhost(HttpServletRequest req)
33 	throws ServletException
34     {
35 	// CONFIG: You must have created /var/zxid directory hierarchy. See `make dir'
36 	// CONFIG: To set config string, edit web.xml (hope you know where it is) and
37 	// add to your servlets sections like
38         //  <servlet>
39 	//    <servlet-name>zxidsrvlet</servlet-name><servlet-class>zxidsrvlet</servlet-class>
40 	//    <init-param>
41 	//      <param-name>ZXIDConf</param-name><param-value>PATH=/var/zxid/</param-value>
42 	//    </init-param>
43 	//  </servlet>
44 	// CONFIG: You must edit the URL to match your domain name and port, usually you
45 	// CONFIG: would create and edit /var/zxid/zxid.conf and override the URL there.
46 	// CONFIG: However, this program sets the URL dynamically, see calls to zxidjni.url_set()
47 	if (cf == null) {
48 	    String conf = getServletConfig().getInitParameter("ZXIDConf");
49 	    cf = zxidjni.new_conf_to_cf(conf);
50 	    zxidjni.set_opt(cf, 1, 1);
51 	}
52 	String scheme = req.getScheme();
53 	String host_hdr = req.getHeader("HOST");
54 	String fullURL = req.getRequestURI();
55 	String url = scheme + "://" + host_hdr + fullURL;
56 	System.err.print("url("+url+")\n");  // URL=http://sp.tas3.pt:8080/zxidservlet/wspdemo
57 	zxidjni.url_set(cf, url);  // Virtual host support
58     }
59 
60     // Only reason why a pure WSP would handle GET is supporting WKL metadata
61     // exchange (o=B). However, a hybrid frontend SP plus WSP would handle its SSO here.
62 
doGet(HttpServletRequest req, HttpServletResponse res)63     public void doGet(HttpServletRequest req, HttpServletResponse res)
64 	throws ServletException, IOException
65     {
66 	System.err.print("Start GET...\n");
67 	init_zxid_vhost(req);
68 	String qs = req.getQueryString();
69 	if (qs != null && (qs.equals("o=B") || qs.equals("o=d"))) {  // Metadata check
70 	    String ret = zxidjni.simple_cf(cf, -1, qs, null, 0x3d54);  // QS response requested
71 	    System.err.print(ret);
72 	    switch (ret.charAt(0)) {
73 	    case 'L':  /* Redirect: ret == "LOCATION: urlCRLF2" */
74 		res.sendRedirect(ret.substring(10, ret.length() - 4));
75 		return;
76 	    case '<':
77 		switch (ret.charAt(1)) {
78 		case 's': case 'm': res.setContentType("text/xml"); break; /* <m20: metadata ... */
79 		default:	    res.setContentType("text/html"); break;
80 		}
81 		res.setContentLength(ret.length());
82 		res.getOutputStream().print(ret);
83 		break;
84 	    default:
85 		System.err.print("Unhandled zxid_simple() response("+ret+").\n");
86 	    }
87 	    return;
88 	}
89 
90 	res.setContentType("text/html");
91 	res.getOutputStream().print("<title>ZXID Demo WSP</title><body><h1>ZXID Demo WSP does not offer web GUI (" + req.getRequestURI() + ")</H1>\n<pre>"+qs+"</pre>");
92     }
93 
94     // Handle a SOAP call, which is always a POST
95 
doPost(HttpServletRequest req, HttpServletResponse res)96     public void doPost(HttpServletRequest req, HttpServletResponse res)
97 	throws ServletException, IOException
98     {
99 	String ret;
100 	System.err.print("\n============ WSP Start SOAP POST ============\n");
101 	init_zxid_vhost(req);
102 	zxidjava.zxid_ses ses = zxidjni.alloc_ses(cf);
103 
104 	// Java / Servlet complicated way of reading in the POST input
105 
106 	String buf;
107 	int len = req.getContentLength();
108 	byte[] b = new byte[len];
109 	int here, got;
110 	for (here = 0; here < len; here += got)
111 	    got = req.getInputStream().read(b, here, len - here);
112 	buf = new String(b, 0, len);
113 
114 	// Check the input for correct ID-WSF compliance
115 
116 	System.err.print("Validating buf("+buf+")\n");
117 	String nid  = zxidjni.wsp_validate(cf, ses, "Resource=demo", buf);
118 	if (nid == null) {
119 	    System.err.print("Validate fail buf("+buf+")\n");
120 	    ret = zxidjni.wsp_decorate(cf, ses, "Resource=demo:fail",
121 				       "<barfoo>"
122 				       + "<lu:Status code=\"Fail\" comment=\"INVALID. Token replay?\"></lu:Status>" +
123 				       "</barfoo>");
124 	    res.getOutputStream().print(ret);
125 	    System.err.print("^^^^^^^^^^^^^ WSP inval ("+ret.length()+" chars output) ^^^^^^^^^^^^^\n\n");
126 	    return;
127 	}
128 	String ldif = zxidjni.ses_to_ldif(cf, ses);
129 	System.err.print("\n===== Doing work for user nid("+nid+").\nAttribute dump: "+ldif+"\n");
130 	ldif = "<img src=\"green-check-20x20.png\">WSP2 Authorized by PDP (B).<br>\n"+ldif+"<img src=\"green-check-20x20.png\">WSP3 Authorized by PDP (B).<br>\n";
131 
132 	// Perform a application dependent authorization step and ship the response
133 
134 	if (zxidjni.az_cf_ses(cf, "Action=Call", ses) == null) {
135 	    System.err.print("Explicit Az fail\n");
136 	    ret = zxidjni.wsp_decorate(cf, ses, "Resource=demo:fail",
137 				       "<barfoo>"
138 				       + "<lu:Status code=\"Fail\" comment=\"Denied\"></lu:Status>"
139 				       + "<data>Denied: nid="+nid+"</data>" +
140 				       "</barfoo>");
141 	} else {
142 	    String recurse = "";
143 	    if (buf.indexOf("STOP") == -1) {
144 		// "http://sp.tas3.pt:8080/zxidservlet/wspleaf?o=B"
145 	ldif = "<img src=\"green-check-20x20.png\">WSP2 Authorized by PDP (B).<br>\n"+ldif+"<img src=\"green-check-20x20.png\">WSP3 Authorized by PDP (B).<br>\n";
146 	        recurse = zxidjni.call(cf, ses, "x-recurs", null, null, "Resource=leaf", "<recursing>STOP</recursing>");
147 	        //recurse = zxidjni.call(cf, ses, "urn:x-foobar", "http://sp.tas3.pt:8080/zxidservlet/wspdemo?o=B", null, null, "<recursing>STOP</recursing>");
148 		System.err.print("Recursive out("+recurse+")\n");
149 		recurse = zxidjni.extract_body(cf, recurse);
150 		recurse += "<img src=\"green-check-20x20.png\">WSC4 Authorized by PDP (B).<br>\n"+ldif+"<img src=\"green-check-20x20.png\">WSP3 Authorized by PDP (B).<br>\n";
151 	    } else {
152 		System.err.print("Recursive STOP\n");
153 	    }
154 
155 	ldif = "<img src=\"green-check-20x20.png\">WSP2 Authorized by PDP (B).<br>\n"+ldif+"<img src=\"green-check-20x20.png\">WSP3 Authorized by PDP (B).<br>\n";
156 
157 	    ret = zxidjni.wsp_decorate(cf, ses, "Resource=demo",
158 				       "<barfoo>"
159 				       + "<lu:Status code=\"OK\" comment=\"Permit\"></lu:Status>"
160 				       + "<data>nid="+nid+"\n"+ldif+"\n\nRECURSE OUT:\n"+recurse+"\n</data>" +
161 				       "</barfoo>");
162 	}
163 
164 	res.getOutputStream().print(ret);
165 	System.err.print("^^^^^^^^^^^^^ WSP Done ("+ret.length()+" chars output) ^^^^^^^^^^^^^\n\n");
166     }
167 }
168 
169 /* EOF */
170 	//String proto = req.getProtocol();
171 	//String servername = req.getServerName();
172 	//int serverport = req.getServerPort();
173 	//String qs = req.getQueryString();
174 	//System.err.print("proto("+proto+")\n");
175 	//System.err.print("scheme("+scheme+")\n");
176 	//System.err.print("servername("+servername+")\n");
177 	//System.err.print("serverport("+serverport+")\n");
178 	//System.err.print("host_hdr("+host_hdr+")\n");
179 	//System.err.print("fullURL("+fullURL+")\n");
180 	//System.err.print("qs("+qs+")\n");
181 	//String url = scheme + "://" + servername
182 	//    + (serverport != 80 && serverport != 443 ? ":"+serverport : "")
183 	//    + fullURL;
184