1 // zxid.java  -  Java CGI script that calls libzxid using JNI
2 // Copyright (c) 2007-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
3 // Author: Sampo Kellomaki (sampo@iki.fi)
4 // This is confidential unpublished proprietary source code of the author.
5 // NO WARRANTY, not even implied warranties. Contains trade secrets.
6 // Distribution prohibited unless authorized in writing.
7 // Licensed under Apache License 2.0, see file COPYING.
8 // $Id: zxid.java,v 1.13 2009-11-29 12:23:06 sampo Exp $
9 // 12.1.2007, created --Sampo
10 
11 import zxidjava.*;
12 
13 public class zxid {
14   static { System.loadLibrary("zxidjni"); }
15 
main(String argv[])16   public static void main(String argv[]) throws java.io.IOException
17   {
18       int ret;
19       zx_str rets;
20       zxid_conf cf;
21       System.err.print("Start...\n");
22 
23       cf = zxidjni.new_conf("/var/zxid/");
24       String url = "https://sp1.zxidsp.org:8443/zxid-java.sh";
25       String cdc_url = "https://sp1.zxidcommon.org:8443/zxid-java.sh";
26       zxidjni.url_set(cf, url);
27       zxidjni.set_opt(cf, 1, 1);
28 
29       String qs = System.getenv("QUERY_STRING");  // Deprecation warnings about this are bogus and indicative of Java designer's disregard of their user base - indeed disconnect from reality, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4199068
30       zxid_cgi cgi = zxidjni.new_cgi(cf, qs);
31       char op = cgi.getOp();
32 
33       if (op == 'P') {
34 	  int len = Integer.parseInt(System.getenv("CONTENT_LENGTH"));
35 	  byte[] b = new byte[len];
36 	  int got = System.in.read(b, 0, len);
37 	  qs = new String(b, 0, got);
38 	  System.err.print("post\n");
39 	  zxidjni.parse_cgi(cgi, qs);
40 	  op = cgi.getOp();
41       }
42 
43       if (op == 0)
44 	  op = 'M';
45 
46       zxid_ses ses;
47       String sid = cgi.getSid();
48       if (sid != null && sid.length() > 0) {
49 	  ses = zxidjni.fetch_ses(cf, sid);
50 	  if (ses != null) {
51 	      if (mgmt_screen(cf, cgi, ses, op) != 0)
52 		  System.exit(0);
53 	  }
54       }
55       ses = zxidjni.fetch_ses(cf, "");  // Just allocate an empty one
56 
57       System.err.println("Not logged in case op="+op+" qs:"+qs);
58 
59       switch (op) {
60       case 'M':       // Invoke LECP or redirect to CDC reader.
61 	  //if (zxidjni.lecp_check(cf, cgi) != 0) System.exit(0);
62 	  System.out.print("Location: " + cdc_url + "?o=C\r\n\r\n");
63 	  System.exit(0);
64       case 'C':  // CDC Read: Common Domain Cookie Reader
65 	  zxidjni.cdc_read(cf, cgi);
66 	  System.exit(0);
67       case 'E':  // Return from CDC read, or start here to by-pass CDC read.
68 	  //if (zxidjni.lecp_check(cf, cgi) != 0) System.exit(0);
69 	  if (zxidjni.cdc_check(cf, cgi) != 0)
70 	      System.exit(0);
71 	  break;
72       case 'L':
73 	  System.err.print("Start login\n");
74 	  url = zxidjni.start_sso_url(cf, cgi).getS();
75 	  if (url.length() > 0) {
76 	      System.err.print("login redir\n");
77 	      System.out.print("Location: " + url + "\r\n\r\n");
78 	      System.exit(0);
79 	  }
80 	  System.err.print("Login trouble");
81 	  break;
82       case 'A':
83 	  ret = zxidjni.sp_deref_art(cf, cgi, ses);
84 	  System.err.println("deref art ret="+ret);
85 	  if (ret == zxidjniConstants.ZXID_REDIR_OK)
86 	      System.exit(0);
87 	  if (ret == zxidjniConstants.ZXID_SSO_OK)
88 	      if (mgmt_screen(cf, cgi, ses, op) != 0)
89 		  System.exit(0);
90 	  break;
91       case 'P':
92 	  // *** broken with newer swig generated -noproxy code
93 	  rets = zxidjni.sp_dispatch(cf, cgi, ses);
94 	  System.err.println("saml_resp ret=" + rets);
95 	  if (rets.getS() == "O")
96 	      System.exit(0);
97 	  if (rets.getS() == "K")
98 	      if (mgmt_screen(cf, cgi, ses, op) != 0)
99 		  System.exit(0);
100 	  break;
101       case 'Q':
102 	  rets = zxidjni.sp_dispatch(cf, cgi, ses);
103 	  if (rets.getS() == "O")
104 	      System.exit(0);
105 	  if (rets.getS() == "K")
106 	      if (mgmt_screen(cf, cgi, ses, op) != 0)
107 		  System.exit(0);
108 	  break;
109       case 'B':
110 	  System.out.print("CONTENT-TYPE: text/xml\r\n\r\n");
111 	  String md = zxidjni.sp_meta(cf, cgi).getS();
112 	  System.out.print(md);
113 	  System.exit(0);
114       default:
115 	  System.err.println("Unknown op="+op);
116       }
117 
118       System.out.print("CONTENT-TYPE: text/html\r\n\r\n");
119 
120 
121       System.out.print("<title>ZXID SP Java SSO</title>\n");
122       System.out.print("<link rel=\"shortcut icon\" href=\"/favicon.ico\" type=\"image/x-icon\" />\n");
123       System.out.print("<body bgcolor=\"#330033\" text=\"#ffaaff\" link=\"#ffddff\" vlink=\"#aa44aa\" alink=\"#ffffff\">\n");
124       System.out.print("<font face=sans><h1>ZXID SP Java Federated SSO (user NOT logged in, no session.)</h1><pre>\n");
125       System.out.print("</pre><form method=post action=\"zxid-java.sh?o=P\">\n");
126 
127       System.out.print("<h3>Login Using New IdP</h3>\n");
128 
129       System.out.print("<i>A new IdP is one whose metadata we do not have yet. We need to know\n");
130       System.out.print("the Entity ID in order to fetch the metadata using the well known\n");
131       System.out.print("location method. You will need to ask the adminstrator of the IdP to\n");
132       System.out.print("tell you what the EntityID is.</i>\n");
133 
134       System.out.print("<p>IdP EntityID URL <input name=e size=100>\n");
135       System.out.print("<input type=submit name=l1 value=\" Login (SAML20:Artifact) \">\n");
136       System.out.print("<input type=submit name=l2 value=\" Login (SAML20:POST) \">\n");
137 
138       zxid_entity idp = zxidjni.load_cot_cache(cf);
139       if (idp != null) {
140 	  System.out.print("<h3>Login Using Known IdP</h3>\n");
141 	  while (idp != null) {
142 	      String eid = idp.getEid();
143 	      int eid_len = idp.getEid_len();
144 	      //eid = substr($eid, 0, $eid_len);
145 	      //warn "eid_len($eid_len) eid($eid)";
146 	      System.out.print("<input type=submit name=\"l1" + eid + "\" value=\" Login to " + eid + " (SAML20:Artifact) \">\n");
147 	      System.out.print("<input type=submit name=\"l2" + eid + "\" value=\" Login to " + eid + " (SAML20:POST) \">\n");
148 	      idp = idp.getN();
149 	  }
150       }
151 
152       String version_str = zxidjni.version_str();
153 
154       System.out.print("<h3>CoT configuration parameters your IdP may need to know</h3>\n");
155 
156       System.out.print("Entity ID of this SP: <a href=\""+url+"?o=B\">"+url+"?o=B</a> (Click on the link to fetch SP metadata.)\n");
157 
158       System.out.print("<h3>Technical options (typically hidden fields on production site)</h3>\n");
159 
160       System.out.print("<input type=checkbox name=fc value=1 checked> Allow new federation to be created<br>\n");
161       System.out.print("<input type=checkbox name=fp value=1> Do not allow IdP to interact (e.g. ask password) (IsPassive flag)<br>\n");
162       System.out.print("<input type=checkbox name=ff value=1> IdP should reauthenticate user (ForceAuthn flag)<br>\n");
163 
164       System.out.print("NID Format: <select name=fn><option value=prstnt>Persistent<option value=trnsnt>Transient<option value=\"\">(none)</select><br>\n");
165       System.out.print("Affiliation: <select name=fq><option value=\"\">(none)</select><br>\n");
166 
167       System.out.print("Consent: <select name=fy><option value=\"\">(empty)\n");
168       System.out.print("<option value=\"urn:liberty:consent:obtained\">obtained\n");
169       System.out.print("<option value=\"urn:liberty:consent:obtained:prior\">obtained:prior\n");
170       System.out.print("<option value=\"urn:liberty:consent:obtained:current:implicit\">obtained:current:implicit\n");
171       System.out.print("<option value=\"urn:liberty:consent:obtained:current:explicit\">obtained:current:explicit\n");
172       System.out.print("<option value=\"urn:liberty:consent:unavailable\">unavailable\n");
173       System.out.print("<option value=\"urn:liberty:consent:inapplicable\">inapplicable\n");
174       System.out.print("</select><br>\n");
175       System.out.print("Authn Req Context: <select name=fa><option value=\"\">(none)\n");
176       System.out.print("<option value=pw>Password\n");
177       System.out.print("<option value=pwp>Password with Protected Transport\n");
178       System.out.print("<option value=clicert>TLS Client Certificate</select><br>\n");
179       System.out.print("Matching Rule: <select name=fm><option value=exact>Exact\n");
180       System.out.print("<option value=minimum>Min\n");
181       System.out.print("<option value=maximum>Max\n");
182       System.out.print("<option value=better>Better\n");
183       System.out.print("<option value=\"\">(none)</select><br>\n");
184       System.out.print("</form><hr><a href=\"http://zxid.org/\">zxid.org</a> " + version_str);
185   }
186 
mgmt_screen(zxid_conf cf, zxid_cgi cgi, zxid_ses ses, char op)187   public static int mgmt_screen(zxid_conf cf, zxid_cgi cgi, zxid_ses ses, char op)
188   {
189       int ret;
190       String msg;
191       zx_str rets;
192       System.err.print("mgmt op=" + op);
193       switch (op) {
194       case 'l':
195 	  zxidjni.del_ses(cf, ses);
196 	  msg = "Local logout Ok. Session terminated.";
197 	  return 0;  // Simply abandon local session. Falls thru to login screen.
198       case 'r':
199 	  zxidjni.sp_slo_redir(cf, cgi, ses);
200 	  zxidjni.del_ses(cf, ses);
201 	  return 1;  // Redirect already happened. Do not show login screen.
202       case 's':
203 	  zxidjni.sp_slo_soap(cf, cgi, ses);
204 	  zxidjni.del_ses(cf, ses);
205 	  msg = "SP Initiated logout (SOAP). Session terminated.";
206 	  return 0;  // Falls thru to login screen.
207       case 't':
208 	  zxidjni.sp_mni_redir(cf, cgi, ses, null);
209 	  return 1;  // Redirect already happened. Do not show login screen.
210       case 'u':
211 	  zxidjni.sp_mni_soap(cf, cgi, ses, null);
212 	  msg = "SP Initiated defederation (SOAP).";
213 	  break;
214       case 'P':
215 	  rets = zxidjni.sp_dispatch(cf, cgi, ses);
216 	  if (rets.getS() == "O") return 0;
217 	  if (rets.getS() == "K") return 1; // REDIR OK
218 	  break;
219       case 'Q':
220 	  rets = zxidjni.sp_dispatch(cf, cgi, ses);
221 	  if (rets.getS() == "O") return 0;
222 	  if (rets.getS() == "K") return 1; // REDIR OK
223 	  break;
224       }
225 
226       String sid = ses.getSid();
227       String nid = ses.getNid();
228 
229       System.out.print("CONTENT-TYPE: text/html\r\n\r\n");
230       System.out.print("<title>ZXID SP Mgmt</title>\n");
231       System.out.print("<link rel=\"shortcut icon\" href=\"/favicon.ico\" type=\"image/x-icon\" />\n");
232       System.out.print("<body bgcolor=\"#330033\" text=\"#ffaaff\" link=\"#ffddff\" vlink=\"#aa44aa\" alink=\"#ffffff\"><font face=sans>\n");
233 
234       System.out.print("<h1>ZXID SP Java Management (user logged in, session active)</h1><pre>\n</pre><form method=post action=\"zxid-java.sh?o=P\">\n");
235       System.out.print("<input type=hidden name=s value=\""+sid+"\">\n");
236       System.out.print("<input type=submit name=gl value=\" Local Logout \">\n");
237       System.out.print("<input type=submit name=gr value=\" Single Logout (Redir) \">\n");
238       System.out.print("<input type=submit name=gs value=\" Single Logout (SOAP) \">\n");
239       System.out.print("<input type=submit name=gt value=\" Defederate (Redir) \">\n");
240       System.out.print("<input type=submit name=gu value=\" Defederate (SOAP) \">\n");
241 
242       System.out.print("<h3>Technical options (typically hidden fields on production site)</h3>\n");
243 
244       System.out.print("sid("+sid+") nid("+nid+") <a href=\"zxid-java.sh?s="+sid+"\">Reload</a>\n");
245       System.out.print("</form><hr>\n");
246       System.out.print("<a href=\"http://zxid.org/\">zxid.org</a>\n");
247       return 1;
248   }
249 }
250 
251 /* EOF */
252