001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/tags/sakai_2-1-1/sample-tools/browser/src/java/org/sakaiproject/tool/sample/BrowserTool.java $
003: * $Id: BrowserTool.java 632 2005-07-14 21:22:50Z janderse@umich.edu $
004: **********************************************************************************
005: *
006: * Copyright (c) 2005 The Regents of the University of Michigan, Trustees of Indiana University,
007: * Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation
008: *
009: * Licensed under the Educational Community License Version 1.0 (the "License");
010: * By obtaining, using and/or copying this Original Work, you agree that you have read,
011: * understand, and will comply with the terms and conditions of the Educational Community License.
012: * You may obtain a copy of the License at:
013: *
014: * http://cvs.sakaiproject.org/licenses/license_1_0.html
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
017: * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
018: * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
019: * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
020: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
021: *
022: **********************************************************************************/package org.sakaiproject.tool.rutgers;
023:
024: import java.io.*;
025:
026: import java.security.*;
027: import java.security.spec.*;
028: import java.security.interfaces.*;
029:
030: import javax.crypto.*;
031: import javax.crypto.spec.*;
032: import javax.crypto.interfaces.*;
033:
034: import java.math.BigInteger;
035:
036: import java.net.URL;
037: import java.net.URLEncoder;
038: import java.text.DateFormat;
039: import java.util.Collection;
040: import java.util.Date;
041: import java.util.Enumeration;
042: import java.util.HashMap;
043: import java.util.HashSet;
044: import java.util.Iterator;
045: import java.util.Map;
046: import java.util.Set;
047: import java.util.Properties;
048: import java.util.regex.Pattern;
049:
050: import javax.servlet.ServletConfig;
051: import javax.servlet.ServletException;
052: import javax.servlet.http.HttpServlet;
053: import javax.servlet.http.HttpServletRequest;
054: import javax.servlet.http.HttpServletResponse;
055:
056: import org.apache.commons.logging.Log;
057: import org.apache.commons.logging.LogFactory;
058: import org.sakaiproject.tool.api.Session;
059: import org.sakaiproject.tool.cover.SessionManager;
060: import org.sakaiproject.tool.cover.ToolManager;
061: import org.sakaiproject.tool.api.Placement;
062: import org.sakaiproject.util.Web;
063: import org.sakaiproject.component.cover.ServerConfigurationService;
064:
065: import org.sakaiproject.site.cover.SiteService;
066: import org.sakaiproject.site.api.Site;
067: import org.sakaiproject.site.api.SitePage;
068:
069: import org.sakaiproject.site.api.ToolConfiguration;
070:
071: import org.sakaiproject.authz.cover.AuthzGroupService;
072: import org.sakaiproject.authz.api.AuthzGroup;
073: import org.sakaiproject.authz.api.Role;
074:
075: import org.sakaiproject.authz.cover.SecurityService;
076:
077: import org.sakaiproject.exception.IdUsedException;
078: import org.sakaiproject.exception.PermissionException;
079:
080: /**
081: * <p>
082: * Sakai browser sample tool.
083: * </p>
084: *
085: * @author University of Michigan, Sakai Software Development Team
086: * @version $Revision: 632 $
087: */
088: public class LinkTool extends HttpServlet {
089: private static final String headHtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\"> <head> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /> <meta http-equiv=\"Content-Style-Type\" content=\"text/css\" /> <title>Link Tool</title>";
090:
091: private static final String headHtml1 = "<script type=\"text/javascript\" language=\"JavaScript\"> var _editor_url = \"/library/htmlarea/\"; function setFrameHeight(id) { var frame = parent.document.getElementById(id); if (frame) { var objToResize = (frame.style) ? frame.style : frame; objToResize.height = \"";
092:
093: private static final String headHtml2 = "\"; }} </script> <script type=\"text/javascript\" language=\"JavaScript\" src=\"/library/htmlarea/htmlarea.js\"> </script> </head><body onload=\"";
094:
095: private static final String headHtml3 = "\" style='margin:0;padding:0;'>";
096:
097: private static final String tailHtml = "</body></html>";
098:
099: private static final String stylesHtml = "<link href='/library/skin/tool_base.css' type='text/css' rel='stylesheet' media='all' /><link href='/library/skin/default/tool.css' type='text/css' rel='stylesheet' media='all' /><script type='text/javascript' language='JavaScript' src='/library/js/headscripts.js'></script>";
100:
101: /** Our log (commons). */
102: private static Log M_log = LogFactory.getLog(LinkTool.class);
103:
104: private static String homedir = null;
105: private static SecretKey secretKey = null;
106: private static SecretKey salt = null;
107: private static String ourUrl = null;
108:
109: /** Helper tool for options. */
110: private static final String OPTIONS_HELPER = "sakai.tool_config.helper";
111:
112: private static final String privkeyname = "sakai.rutgers.linktool.privkey";
113: private static final String saltname = "sakai.rutgers.linktool.salt";
114:
115: private Set illegalParams;
116: private Pattern legalKeys;
117:
118: /**
119: * Access the Servlet's information display.
120: *
121: * @return servlet information.
122: */
123: public String getServletInfo() {
124: return "Link Tool";
125: }
126:
127: /**
128: * Initialize the servlet.
129: *
130: * @param config
131: * The servlet config.
132: * @throws ServletException
133: */
134: public void init(ServletConfig config) throws ServletException {
135: super .init(config);
136: homedir = ServerConfigurationService.getSakaiHomePath();
137: if (homedir == null)
138: homedir = "/etc/";
139:
140: // System.out.println("canread " + homedir + pubkeyname + (new File(homedir + pubkeyname)).canRead());
141: // System.out.println("canread " + homedir + privkeyname + (new File(homedir + privkeyname)).canRead());
142:
143: if (!(new File(homedir + privkeyname)).canRead()) {
144: genkey(homedir);
145: }
146:
147: // System.out.println("canread public " + (new File(homedir + pubkeyname)).canRead());
148: // System.out.println("canread private " + (new File(homedir + privkeyname)).canRead());
149:
150: secretKey = readSecretKey(homedir + privkeyname, "Blowfish");
151: // if (secretKey != null)
152: // System.out.println("got private key");
153:
154: if (!(new File(homedir + saltname)).canRead()) {
155: gensalt(homedir);
156: }
157:
158: salt = readSecretKey(homedir + saltname, "HmacSHA1");
159:
160: ourUrl = ServerConfigurationService
161: .getString("sakai.rutgers.linktool.serverUrl");
162: // System.out.println("linktool url " + ourUrl);
163: if (ourUrl == null || ourUrl.equals(""))
164: ourUrl = ServerConfigurationService.getString("serverUrl");
165: // System.out.println("linktool url " + ourUrl);
166: if (ourUrl == null || ourUrl.equals(""))
167: ourUrl = "http://127.0.0.1:8080";
168:
169: // System.out.println("linktool url " + ourUrl);
170:
171: illegalParams = new HashSet();
172: illegalParams.add("user");
173: illegalParams.add("internaluser");
174: illegalParams.add("site");
175: illegalParams.add("role");
176: illegalParams.add("session");
177: illegalParams.add("serverurl");
178: illegalParams.add("url");
179: illegalParams.add("time");
180: illegalParams.add("sign");
181:
182: legalKeys = Pattern.compile("^[a-zA-Z0-9]+$");
183:
184: M_log.info("init()");
185: }
186:
187: /**
188: * Shutdown the servlet.
189: */
190: public void destroy() {
191: M_log.info("destroy()");
192:
193: super .destroy();
194: }
195:
196: /**
197: * Respond to Get requests:
198: * display main content by redirecting to it and adding
199: * user= euid= site= role= serverurl= time= sign=
200: * for privileged users, add a bar at the top with a link to
201: * the setup screen
202: * ?Setup generates the setup screen
203: *
204: * @param req
205: * The servlet request.
206: * @param res
207: * The servlet response.
208: * @throws ServletException.
209: * @throws IOException.
210: */
211:
212: protected void doGet(HttpServletRequest req, HttpServletResponse res)
213: throws ServletException, IOException {
214:
215: // get the Tool
216: Placement placement = ToolManager.getCurrentPlacement();
217: Properties config = null;
218: if (placement != null)
219: config = placement.getConfig();
220: PrintWriter out = res.getWriter();
221: res.setContentType("text/html");
222:
223: String userid = null;
224: String euid = null;
225: String siteid = null;
226: String sessionid = null;
227: String url = null;
228: String command = null;
229: String signature = null;
230: String element = null;
231: String oururl = req.getRequestURI();
232: String query = req.getQueryString();
233:
234: // set frame height
235:
236: StringBuffer bodyonload = new StringBuffer();
237: if (placement != null) {
238: element = Web.escapeJavascript("Main" + placement.getId());
239: bodyonload.append("setFrameHeight('" + element + "');");
240: }
241:
242: // prepare the data for the redirect
243:
244: // we can always get the userid from the session
245: Session s = SessionManager.getCurrentSession();
246: if (s != null) {
247: // System.out.println("got session " + s.getId());
248: userid = s.getUserId();
249: euid = s.getUserEid();
250: sessionid = s.getId();
251: }
252:
253: if (userid != null && (euid == null || euid.equals("")))
254: euid = userid;
255:
256: // site is there only for tools, otherwise have to use user's arg
257: // this is safe because we verify that the user has a role in site
258: if (placement != null)
259: siteid = placement.getContext();
260: if (siteid == null)
261: siteid = req.getParameter("site");
262:
263: // if user has asked for a url, use it
264: url = req.getParameter("url");
265: // else take it from the tool config
266: if (url == null && config != null)
267: url = config.getProperty("url", null);
268:
269: // now get user's role in site; must be defined
270: String realmId = null;
271: AuthzGroup realm = null;
272: Role r = null;
273: String rolename = null;
274:
275: if (siteid != null)
276: realmId = SiteService.siteReference(siteid);
277: if (realmId != null) {
278: try {
279: realm = AuthzGroupService.getAuthzGroup(realmId);
280: } catch (Exception e) {
281: }
282: }
283: if (realm != null && userid != null)
284: r = realm.getUserRole(userid);
285: if (r != null) {
286: rolename = r.getId();
287: }
288:
289: if (sessionid != null)
290: sessionid = encrypt(sessionid);
291:
292: // generate redirect, as url?user=xxx&site=xxx
293:
294: if (url != null && userid != null && siteid != null
295: && rolename != null && sessionid != null) {
296: // command is the thing that will be signed
297: command = "user=" + URLEncoder.encode(euid)
298: + "&internaluser=" + URLEncoder.encode(userid)
299: + "&site=" + URLEncoder.encode(siteid) + "&role="
300: + URLEncoder.encode(rolename) + "&session="
301: + URLEncoder.encode(sessionid) + "&serverurl="
302: + URLEncoder.encode(ourUrl) + "&time="
303: + System.currentTimeMillis();
304:
305: // pass on any other arguments from the user.
306: // but sanitize them to prevent people from trying to
307: // fake out the parameters we pass, or using odd syntax
308: // whose effect I can't predict
309: Map params = req.getParameterMap();
310: Set entries = params.entrySet();
311: Iterator pIter = entries.iterator();
312: while (pIter.hasNext()) {
313: Map.Entry entry = (Map.Entry) pIter.next();
314: String key = "";
315: String value = "";
316: try {
317: key = (String) entry.getKey();
318: value = ((String[]) entry.getValue())[0];
319: } catch (Exception ignore) {
320: }
321: if (!illegalParams.contains(key.toLowerCase())
322: && legalKeys.matcher(key).matches())
323: command = command + "&" + key + "="
324: + URLEncoder.encode(value);
325: }
326:
327: try {
328: // System.out.println("sign >" + command + "<");
329: signature = sign(command);
330: url = url + "?" + command + "&sign=" + signature + "';";
331: bodyonload.append("window.location = '" + url);
332: } catch (Exception e) {
333: }
334: ;
335: }
336:
337: // now put out a vestigial web page, whose main functional
338: // part is actually the <body onload=
339:
340: int height = 600;
341: String heights;
342: if (config != null) {
343: heights = safetrim(config.getProperty("height", "600"));
344: if (heights.endsWith("px"))
345: heights = safetrim(heights.substring(0, heights
346: .length() - 2));
347: height = Integer.parseInt(heights);
348: }
349:
350: // now generate the page
351:
352: // User asked for setup menu
353: // if (query != null)
354: // System.out.println("query: " + query);
355: // else
356: // System.out.println("no query");
357: if (query != null && query.equals("Setup")) {
358: if (writeSetupPage(out, placement, element, config, oururl))
359: return;
360: }
361:
362: // If user can update site, add config menu
363: // placement and config should be defined in tool mode
364: // in non-tool mode, there's no config to update
365: if (placement != null && config != null
366: && SiteService.allowUpdateSite(siteid)) {
367: if (writeOwnerPage(out, height, url, element, oururl))
368: return;
369: }
370:
371: // default output - show the requested application
372: out.println(headHtml + headHtml1 + height + "px" + headHtml2
373: + bodyonload + headHtml3);
374: out.println(tailHtml);
375:
376: // res.sendRedirect(res.encodeRedirectURL(config.getProperty("url", "/")));
377:
378: }
379:
380: /**
381: * Called by doGet to display the main contents. Differs from
382: * the default output in that it adds a bar at the top containing
383: * a link to the Setup option.
384: *
385: * @param out
386: * printwriter generating web display
387: * @param height
388: * height of the window to display
389: * @param url
390: * url to redirect to
391: * @param element
392: * Javascript window id
393: * @param oururl
394: * URL for this application
395: */
396:
397: private boolean writeOwnerPage(PrintWriter out, int height,
398: String url, String element, String oururl) {
399:
400: String bodyonload = "";
401:
402: if (url == null)
403: return false;
404:
405: if (element != null)
406: bodyonload = "setFrameHeight('" + element + "');";
407:
408: out.println(headHtml + headHtml1 + (height + 30) + "px"
409: + headHtml2 + bodyonload + headHtml3);
410: out
411: .println("<div><div style='color:#000;text-align:center;font-size:.9em;padding-bottom:5px;line-height:1.3em;background:#DDDDDD;height:22px;overflow:hidden'><a href='"
412: + oururl
413: + "?Setup' style='border-bottom:1px dashed #999999;color:black;text-decoration:none;font:80% Verdana,Arial,Helvetica,sans-serif'>Setup</a></div></div><iframe src='"
414: + url
415: + "' height='"
416: + height
417: + "px' width='100%' frameborder='0' marginwidth='0' marginheight='0'></iframe>");
418:
419: out.println(tailHtml);
420:
421: return true;
422: }
423:
424: /**
425: * Called by doGet to display the main contents. Differs from
426: * the default output in that it adds a bar at the top containing
427: * a link to the Setup option.
428: *
429: * @param out
430: * printwriter generating web display
431: * @param placement
432: * Sakai Placement struct for this tool
433: * @param element
434: * Javascript window id
435: * @param config
436: * Properties list for this tool
437: * @param oururl
438: * URL for this application
439: */
440:
441: private boolean writeSetupPage(PrintWriter out,
442: Placement placement, String element, Properties config,
443: String oururl) {
444: String bodyonload = "";
445:
446: // if not in tool mode, nothing to do
447: if (placement == null || config == null)
448: return false;
449:
450: if (element != null)
451: bodyonload = "setMainFrameHeight('" + element
452: + "');setFocus(focus_path);";
453:
454: out.println(headHtml);
455: out.println(stylesHtml);
456: out.println(headHtml1 + "300px" + headHtml2 + bodyonload
457: + headHtml3);
458: // out.println("<h2>Setup page</h2>");
459: out.println("<div class='portletBody'><h2>Setup</h2>");
460: out.println("<form method='post' action='" + oururl
461: + "?SetupForm'>");
462: out.println("URL: <input type=text name=url size=70 value='"
463: + config.getProperty("url") + "'><br>");
464: out.println("Height: <input type=text name=height value='"
465: + config.getProperty("height") + "'><br>");
466: if (placement != null)
467: out.println("Page title: <input type=text name=title><br>");
468: out.println("<input type=submit value='Update Configuration'>");
469: out.println("</form>");
470: out
471: .println("<p>NOTE: setting the Page title changes the title for the entire page (i.e. what is in the left margin). If there is more than one tool on the page, this may not be what you want to do. Admittedly, having more than one tool on the page is fairly rare.");
472:
473: out.println("<h3>Session Access</h3>");
474: out
475: .println("<p> This section allows you to request a cryptographically signed object that can be used to request access to a Sakai session ID. Session IDs are needed to access most of the web services. ");
476:
477: // Session s = SessionManager.getCurrentSession();
478: // String userid = null;
479: // if (s != null) {
480: // // System.out.println("got session " + s.getId());
481: // userid = s.getUserId();
482: //}
483:
484: boolean isprived = SecurityService.getInstance().isSuperUser();
485: // System.out.println("user " + userid + "prived " + isprived);
486: if (!isprived) {
487: out
488: .println("<p>You can request an object that will generate a session logged with your userid. For applications that deal with sites that you own, such an object should be sufficient for most purposes.");
489: out
490: .println("<p>For applications that need to create site or users, or deal with many sites, an administrator can generate objects with more privileges");
491: out.println("<form method='post' action='" + oururl
492: + "?SignForm'>");
493: out
494: .println("<input type=submit value='Generate Signed Object'>");
495: out.println("</form>");
496: } else {
497: out
498: .println("<p>As a privileged user, you can request an object that will generate a session logged in as any user. For applications that just deal with a single site, and which need site owner privileges, you should ask for an object in the name of the site owner. For applications that need to create site or users, or deal with many sites, you should ask for an object in the name of a user with administrative privileges. If you generate an object in the name of an administrator, please be careful only to put it in sites whose security you trust.<p>You can also request a second kind of object. This one will generate a session for the current user. That is, when an end user accesses an application, this will return a session for that end user. Please be careful about what sites you put this in, because it will allow the owner of the site to compromise the privacy of any user using the site.");
499:
500: out.println("<form method='post' action='" + oururl
501: + "?SignForm'>");
502: out
503: .println("Specific user: <input type=text name=user size=30> [an internal Sakai user, not the Enterprise ID]<br>");
504: out
505: .println("The current user: <input type=checkbox name=current value=yes><br>");
506: out
507: .println("<input type=submit value='Generate Signed Object'>");
508: out.println("</form>");
509: }
510:
511: // if (SecurityService.getInstance().isSuperUser())
512:
513: out
514: .println("<h3>Exit</h3><p><form action='"
515: + oururl
516: + "?panel=Main' method='get'><input type=submit value='Exit Setup'></form>");
517: out.println("</div>");
518:
519: out.println(tailHtml);
520: return true;
521: }
522:
523: /**
524: * Output a page with an error message on it
525: *
526: * @param out
527: * printwriter generating web display
528: * @param element
529: * Javascript window id
530: * @param error
531: * the actual error message
532: * @param oururl
533: * URL for this application
534: */
535:
536: private boolean writeErrorPage(PrintWriter out, String element,
537: String error, String oururl) {
538:
539: String bodyonload = "";
540:
541: if (element != null)
542: bodyonload = "setMainFrameHeight('" + element
543: + "');setFocus(focus_path);";
544:
545: out.println(headHtml);
546: out.println(stylesHtml);
547: out.println(headHtml1 + "300px" + headHtml2 + bodyonload
548: + headHtml3);
549:
550: out.println("<div class='portletBody'><h2>Error</h2>");
551: out.println("<p>" + error);
552:
553: out.println("<p><a href='" + oururl
554: + "?panel=Main'>Return to tool</a>");
555: out.println("</div>");
556:
557: out.println(tailHtml);
558: return true;
559: }
560:
561: /**
562: * Respond to data posting requests. Request we support are
563: * ?SetupForm - when Setup form is submitted. Implement the
564: * changes and redisplay the setup form with the updated values
565: * ?SignForm - when user submits a request for us to generate a
566: * signed object. Generate the object and display it
567: *
568: * @param req
569: * The servlet request.
570: * @param res
571: * The servlet response.
572: * @throws ServletException.
573: * @throws IOException.
574: */
575: protected void doPost(HttpServletRequest req,
576: HttpServletResponse res) throws ServletException,
577: IOException {
578: String query = req.getQueryString();
579: if (query.equals("SignForm")) {
580: doSignForm(req, res);
581: return;
582: }
583:
584: Placement placement = ToolManager.getCurrentPlacement();
585: Properties config = null;
586: PrintWriter out = res.getWriter();
587: String userid = null;
588: String siteid = null;
589: String url = null;
590: String command = null;
591: String signature = null;
592: String element = null;
593: String oururl = req.getRequestURI();
594:
595: // must be in tool mode
596: if (placement == null) {
597: writeErrorPage(out, element,
598: "Unable to find the current tool", oururl);
599: return;
600: }
601:
602: // site is there only for tools, otherwise have to use user's arg
603: // this is safe because we verify that the user has a role in site
604: siteid = placement.getContext();
605: if (siteid == null) {
606: writeErrorPage(out, element,
607: "Unable to find the current site", oururl);
608: return;
609: }
610:
611: Session s = SessionManager.getCurrentSession();
612: if (s != null) {
613: // System.out.println("got session " + s.getId());
614: userid = s.getUserId();
615: }
616:
617: if (userid == null) {
618: writeErrorPage(out, element,
619: "Unable to figure out your userid", oururl);
620: return;
621: }
622: if (!SiteService.allowUpdateSite(siteid)) {
623: writeErrorPage(out, element,
624: "You are not allowed to update this site", oururl);
625: return;
626: }
627:
628: ToolConfiguration toolConfig = SiteService.findTool(placement
629: .getId());
630:
631: placement.getPlacementConfig().setProperty("url",
632: safetrim(req.getParameter("url")));
633: placement.getPlacementConfig().setProperty("height",
634: safetrim(req.getParameter("height")));
635:
636: String newtitle = safetrim(req.getParameter("title"));
637: if (newtitle != null && newtitle.equals(""))
638: newtitle = null;
639:
640: if (newtitle != null) {
641:
642: placement.setTitle(safetrim(req.getParameter("title")));
643:
644: if (toolConfig != null) {
645: try {
646: Site site = SiteService.getSite(toolConfig
647: .getSiteId());
648: SitePage page = site
649: .getPage(toolConfig.getPageId());
650: page.setTitle(safetrim(req.getParameter("title")));
651: SiteService.save(site);
652: } catch (Exception ignore) {
653: }
654: }
655:
656: }
657:
658: placement.save();
659:
660: if (placement != null)
661: element = Web.escapeJavascript("Main" + placement.getId());
662:
663: if (placement != null)
664: config = placement.getConfig();
665: writeSetupPage(out, placement, element, config, oururl);
666:
667: }
668:
669: /**
670: * Respond to data posting requests. Called from doPost for
671: * ?SignForm - when user submits a request for us to generate a
672: * signed object. Generate the object and display it
673: *
674: * @param req
675: * The servlet request.
676: * @param res
677: * The servlet response.
678: * @throws ServletException.
679: * @throws IOException.
680: */
681:
682: private void doSignForm(HttpServletRequest req,
683: HttpServletResponse res) throws ServletException,
684: IOException {
685: Placement placement = ToolManager.getCurrentPlacement();
686: PrintWriter out = res.getWriter();
687: String userid = null;
688: String element = null;
689: String command = null;
690: String signature = null;
691: String oururl = req.getRequestURI();
692: String object = null;
693: String bodyonload = null;
694:
695: if (placement != null)
696: element = Web.escapeJavascript("Main" + placement.getId());
697: else {
698: writeErrorPage(out, element,
699: "Unable to find the current tool", oururl);
700: return;
701: }
702:
703: Session s = SessionManager.getCurrentSession();
704: if (s != null) {
705: // System.out.println("got session " + s.getId());
706: userid = s.getUserId();
707: }
708:
709: if (userid == null) {
710: writeErrorPage(out, element,
711: "Unable to figure out your userid", oururl);
712: return;
713: }
714:
715: boolean isprived = SecurityService.getInstance().isSuperUser();
716:
717: if (isprived) {
718: String requser = safetrim(req.getParameter("user"));
719: String current = safetrim(req.getParameter("current"));
720:
721: if (current != null && current.equals("yes"))
722: command = "currentuser";
723: else if (requser != null & !requser.equals(""))
724: command = "user=" + requser;
725: else {
726: writeErrorPage(out, element, "No username supplied",
727: oururl);
728: return;
729: }
730:
731: } else {
732: command = "user=" + userid;
733: }
734:
735: if (command != null) {
736: try {
737: signature = sign(command);
738: object = command + "&sign=" + signature;
739: } catch (Exception e) {
740: }
741: ;
742: }
743:
744: if (object == null) {
745: writeErrorPage(out, element,
746: "Attempt to generate signed object failed", oururl);
747: return;
748: }
749:
750: bodyonload = "setMainFrameHeight('" + element
751: + "');setFocus(focus_path);";
752:
753: out.println(headHtml);
754: out.println(stylesHtml);
755: out.println(headHtml1 + "300px" + headHtml2 + bodyonload
756: + headHtml3);
757:
758: out.println("<div class='portletBody'><h2>Your object</h2>");
759: out
760: .println("<p>Here is your object. You should copy it and then paste it into a configuration file to be used in your application.");
761: out.println("<p>" + object);
762:
763: out.println("<p><a href='" + oururl
764: + "?panel=Main'>Return to tool</a>");
765: out.println("</div>");
766:
767: out.println(tailHtml);
768:
769: }
770:
771: /**
772: * Sign a string with our private signing key. Returns a hex string
773: *
774: * @param data
775: * The data to sign
776: * @throws Exception.
777: */
778:
779: private static String sign(String data) throws Exception {
780: Mac sig = Mac.getInstance("HmacSHA1");
781: sig.init(salt);
782: return byteArray2Hex(sig.doFinal(data.getBytes()));
783: }
784:
785: /**
786: * Read our secret key from a file. returns the key
787: *
788: * @param filename
789: * Contains the key in proper binary format
790: */
791:
792: private static SecretKey readSecretKey(String filename, String alg) {
793: try {
794: FileInputStream file = new FileInputStream(filename);
795: byte[] bytes = new byte[file.available()];
796: file.read(bytes);
797: file.close();
798: SecretKey privkey = new SecretKeySpec(bytes, alg);
799: return privkey;
800: } catch (Exception ignore) {
801: return null;
802: }
803: }
804:
805: private static char[] hexChars = { '0', '1', '2', '3', '4', '5',
806: '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
807:
808: /**
809: * Convert byte array to hex string
810: *
811: * @param ba
812: * array of bytes
813: * @throws Exception.
814: */
815:
816: private static String byteArray2Hex(byte[] ba) {
817: StringBuffer sb = new StringBuffer();
818: for (int i = 0; i < ba.length; i++) {
819: int hbits = (ba[i] & 0x000000f0) >> 4;
820: int lbits = ba[i] & 0x0000000f;
821: sb.append("" + hexChars[hbits] + hexChars[lbits]);
822: }
823: return sb.toString();
824: }
825:
826: /**
827: * Version of trim that won't blow up if fed null
828: *
829: * @param a
830: * string
831: */
832:
833: private String safetrim(String s) {
834: if (s == null)
835: return null;
836: return s.trim();
837: }
838:
839: // genkey
840:
841: // from http://www.cs.ru.nl/~martijno/
842: // Martijn Oostdijk. by permission
843:
844: /**
845: * Generate a secret key, and write it to a file
846: *
847: * @param dirname
848: * writes to file privkeyname in this
849: * directory. dirname assumed to end in /
850: */
851:
852: private void genkey(String dirname) {
853: try {
854: /* Generate key. */
855: System.out.println("Generating key...");
856: SecretKey key = KeyGenerator.getInstance("Blowfish")
857: .generateKey();
858:
859: /* Write private key to file. */
860: writeKey(key, dirname + privkeyname);
861:
862: } catch (Exception e) {
863: e.printStackTrace();
864: }
865: }
866:
867: /**
868: * Writes <code>key</code> to file with name <code>filename</code>
869: *
870: * @throws IOException if something goes wrong.
871: */
872: private static void writeKey(Key key, String filename)
873: throws IOException {
874: FileOutputStream file = new FileOutputStream(filename);
875: file.write(key.getEncoded());
876: file.close();
877: }
878:
879: // gensalt
880:
881: /**
882: * Generate a random salt, and write it to a file
883: *
884: * @param dirname
885: * writes to file saltname in this
886: * directory. dirname assumed to end in /
887: */
888:
889: private void gensalt(String dirname) {
890: try {
891: // Generate a key for the HMAC-SHA1 keyed-hashing algorithm
892: KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA1");
893: SecretKey key = keyGen.generateKey();
894: writeKey(key, dirname + saltname);
895: } catch (Exception e) {
896: e.printStackTrace();
897: }
898: }
899:
900: public String encrypt(String str) {
901: try {
902: Cipher ecipher = Cipher.getInstance("Blowfish");
903: ecipher.init(Cipher.ENCRYPT_MODE, secretKey);
904:
905: // Encode the string into bytes using utf-8
906: byte[] utf8 = str.getBytes("UTF8");
907:
908: // Encrypt
909: byte[] enc = ecipher.doFinal(utf8);
910:
911: // Encode bytes to base64 to get a string
912: return byteArray2Hex(enc);
913: } catch (javax.crypto.BadPaddingException e) {
914: System.out.println("linktool encrypt bad padding");
915: } catch (javax.crypto.IllegalBlockSizeException e) {
916: System.out.println("linktool encrypt illegal block size");
917: } catch (java.security.NoSuchAlgorithmException e) {
918: System.out.println("linktool encrypt no such algorithm");
919: } catch (java.security.InvalidKeyException e) {
920: System.out.println("linktool encrypt invalid key");
921: } catch (javax.crypto.NoSuchPaddingException e) {
922: System.out.println("linktool encrypt no such padding");
923: } catch (java.io.UnsupportedEncodingException e) {
924: System.out.println("linktool encrypt unsupported encoding");
925: } catch (java.io.IOException e) {
926: System.out.println("linktool encrypted io exc");
927: }
928: return null;
929: }
930:
931: }
|