/*
* @(#)RealmDumpServlet.java 1.16 97/10/25
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.0
*/
import java.io.*;
import java.security.Principal;
import java.security.acl.Acl;
import java.security.acl.Group;
import java.util.*;
import javax.servlet.http.*;
import com.sun.server.realm.*;
/**
* This class dumps realm data, using either the application interface
* (invoke a static main method) or an HTTP servlet interface.
*
* By default it dumps all the data in all of the realms. Options may
* be used to control what data is dumped. There is no default realm,
* though many sites are expected to want to use only a single realm.
*
*
Options supported by the application interface are:
*
*
* -html |
* The output of this command is a single HTML document. |
*
*
*
* -realm realmName |
* Dumps only the named realm. |
*
*
*
* -acls |
* Dumps acls in the selected domain(s). |
*
*
*
* -groups |
* Dumps groups in the selected domain(s). |
*
*
*
* -users |
* Dumps users in the selected domain(s). |
*
*
*
*
* @version 1.16
* @author David Brownell
*/
public class RealmDumpServlet extends HttpServlet
{
//
// Option flags settable from the command line or via HTML
// forms ... initial values are specified by the language spec.
// Keep these in alphabetical order; helps keep it in sync
// with the documentation above.
//
private boolean useHTML;
private String onlyRealm;
private boolean doACLs;
private boolean doGroups;
private boolean doUsers;
//
// Statistics gathered during this run:
//
private int realmCount;
private int userCount;
private int groupCount;
private int aclCount;
/**
* Standard command line entry point; the command line options
* are processed, and output is generated on the command's standard
* output stream.
*
* @param argv command line argument vector
*/
public static void main (String argv [])
{
RealmDumpServlet d = new RealmDumpServlet ();
PrintWriter out = new PrintWriter (System.out, true);
try {
// d.mutateGroups ();
d.doCommand (argv, out);
out.flush ();
} catch (Exception e) {
e.printStackTrace ();
}
}
////// BEGIN DEBUGGING CODE
private void mutateGroups ()
{
try {
Realm r = Realm.get ("adminRealm");
Vector principals = new Vector ();
int seed = 0x7fffffff & new Random ().nextInt ();
//
// Collect all the principals in the realm.
//
for (Enumeration e = r.getUserNames (); e.hasMoreElements (); )
principals.addElement (r.getUser ((String) e.nextElement ()));
for (Enumeration e = r.getGroupNames (); e.hasMoreElements (); )
principals.addElement (r.getGroup ((String) e.nextElement ()));
//
// Create a new group, and populate it with some of the
// earlier members of the list of principals.
//
Group g = r.addGroup ("G-" + seed);
for (int i = 0; i < principals.size () && i < 31; i++) {
if ((seed & (0x01 << i)) != 0)
g.addMember ((Principal) principals.elementAt (i));
}
//
// See if we can delete the last group in the list ...
// the main reason we couldn't is if we happened to add
// it to the group we just created. We want to know that
// fails cleanly anyway, so this is "always" interesting.
//
Object o = principals.lastElement ();
if (o instanceof Group) {
g = (Group) o;
r.removeGroup (g.toString ());
}
} catch (Exception e) {
e.printStackTrace (System.err);
}
}
////// END DEBUG CODE
/**
* General purpose entry to the realm dumping facility.
*
* @param argv command line argument vector
* @param out where to emit the text.
*/
public void doCommand (String argv [], PrintWriter out)
throws IOException
{
//
// Parse the "command line" arguments.
//
for (int i = 0; i < argv.length; i++) {
if (argv [i].equals ("-html"))
useHTML = true;
else if (argv [i].equals ("-acls"))
doACLs = true;
else if (argv [i].equals ("-groups"))
doGroups = true;
else if (argv [i].equals ("-users"))
doUsers = true;
else if (argv [i].equals ("-realm") && ((i + 1) < argv.length))
onlyRealm = argv [++i];
else
throw new IllegalArgumentException (argv [i]);
}
emit (out, null, true);
}
/**
* HTTP GET operations sent to this servlet producs a form which
* may be used to control which realm is being looked at.
*/
// XXX note bug: state is servlet-global, could be changed by
// a concurrent request. We really want to be able to associate
// servlet instances with sessions, and have per-session state.
public void doGet (
HttpServletRequest request,
HttpServletResponse response
) throws IOException
{
useHTML = true;
response.setContentType ("text/html");
emit (response.getWriter (), request.getServletPath (), false);
}
/**
* POSTing to this servlet uses form data to provide a detailed
* look at a single realm.
*/
// XXX note bug: state is servlet-global, could be changed by
// a concurrent request.
public void doPost (
HttpServletRequest request,
HttpServletResponse response
) throws IOException
{
String temp;
useHTML = true;
response.setContentType ("text/html");
temp = request.getParameter ("showACLs");
if (temp != null && temp.equalsIgnoreCase ("true"))
doACLs = true;
temp = request.getParameter ("showGroups");
if (temp != null && temp.equalsIgnoreCase ("true"))
doGroups = true;
temp = request.getParameter ("showUsers");
if (temp != null && temp.equalsIgnoreCase ("true"))
doUsers = true;
temp = request.getParameter ("onlyRealm");
if (temp != null && !temp.equalsIgnoreCase (""))
onlyRealm = temp;
emit (response.getWriter (), request.getServletPath (), true);
}
// emit HTML page, maybe with POST form, maybe with data
private void emit (
PrintWriter out,
String relativePostURL,
boolean dumpAll
) throws IOException
{
//
// Start emitting the output.
//
if (useHTML) {
out.println ("");
out.println ("REALM DUMP");
out.println ("");
out.println ("");
}
//
// The servlet is driven by posting to a form which it
// generates. Emit the form if it's appropriate.
//
if (relativePostURL != null) {
Realm r;
out.print ("
");
}
if (dumpAll) try {
out.println (header (1, "Realm Dump"));
out.println ("Produced: " + new Date ());
//
// If we're dumping only one realm, that's a simple case.
//
if (onlyRealm != null) {
Realm r = Realm.get (onlyRealm);
dump (r, out);
//
// Enumerate all the realms, dumping each one.
//
} else {
Vector realmNames = new Vector ();
Realm r;
for (Enumeration e = Realm.getRealmNames ();
e.hasMoreElements ();
realmNames.addElement (e.nextElement ()))
continue;
if (useHTML) {
out.println ("");
for (int i = 0; i < realmNames.size (); i++) {
String name = (String) realmNames.elementAt (i);
out.println ("- " + href ("Realm",
name, // realm for tag
name // text seen by user
));
}
out.println ("
");
}
for (int i = 0; i < realmNames.size (); i++) {
r = Realm.get ((String) realmNames.elementAt (i));
if (useHTML) {
out.println ("
");
out.println (anchor ("Realm", r));
out.println ("");
}
dump (r, out);
}
if (useHTML)
out.println ("
");
}
out.println (header (2, "Statistics"));
out.println (" Realms = " + realmCount);
out.println (" Users = " + userCount);
out.println (" Groups = " + groupCount);
out.println (" ACLs = " + aclCount);
} catch (Exception e) {
e.printStackTrace (out);
if (useHTML)
out.println ("
");
return;
}
if (useHTML)
out.println ("