JBossWeb SVN: r1584 - trunk/java/org/apache/catalina/servlets.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2010-11-23 05:18:39 -0500 (Tue, 23 Nov 2010)
New Revision: 1584
Modified:
trunk/java/org/apache/catalina/servlets/CGIServlet.java
Log:
- Port CGI updates.
Modified: trunk/java/org/apache/catalina/servlets/CGIServlet.java
===================================================================
--- trunk/java/org/apache/catalina/servlets/CGIServlet.java 2010-11-23 10:13:25 UTC (rev 1583)
+++ trunk/java/org/apache/catalina/servlets/CGIServlet.java 2010-11-23 10:18:39 UTC (rev 1584)
@@ -41,7 +41,6 @@
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
-import javax.servlet.UnavailableException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -123,7 +122,7 @@
* or an instance where the specification cited differs from Best
* Community Practice (BCP).
* Such instances should be well-documented here. Please email the
- * <a href="mailto:tomcat-dev@jakarta.apache.org">Jakarta Tomcat group [tomcat-dev(a)jakarta.apache.org]</a>
+ * <a href="mailto:dev@tomcat.apache.org">Tomcat group [dev(a)tomcat.apache.org]</a>
* with amendments.
*
* </p>
@@ -179,7 +178,7 @@
* </p>
* <p>
*
- * <b>Metavariable Values</b>: According to the CGI specificion,
+ * <b>Metavariable Values</b>: According to the CGI specification,
* implementations may choose to represent both null or missing values in an
* implementation-specific manner, but must define that manner. This
* implementation chooses to always define all required metavariables, but
@@ -192,7 +191,7 @@
*
* <b>NPH -- Non-parsed-header implementation</b>: This implementation does
* not support the CGI NPH concept, whereby server ensures that the data
- * supplied to the script are preceisely as supplied by the client and
+ * supplied to the script are precisely as supplied by the client and
* unaltered by the server.
* </p>
* <p>
@@ -227,15 +226,13 @@
* <li> Better documentation
* <li> Confirm use of ServletInputStream.available() in CGIRunner.run() is
* not needed
- * <li> Make checking for "." and ".." in servlet & cgi PATH_INFO less
- * draconian
* <li> [add more to this TODO list]
* </ul>
* </p>
*
* @author Martin T Dengler [root(a)martindengler.com]
* @author Amy Roh
- * @version $Revision$, $Date$
+ * @version $Id$
* @since Tomcat 4.0
*
*/
@@ -245,6 +242,8 @@
/* some vars below copied from Craig R. McClanahan's InvokerServlet */
+ private static final long serialVersionUID = 1L;
+
/** the debugging detail level for this servlet. */
private int debug = 0;
@@ -260,9 +259,15 @@
private String cgiExecutable = "perl";
/** the encoding to use for parameters */
- private String parameterEncoding = System.getProperty("file.encoding",
- "UTF-8");
+ private String parameterEncoding =
+ System.getProperty("file.encoding", "UTF-8");
+ /**
+ * The time (in milliseconds) to wait for the reading of stderr to complete
+ * before terminating the CGI process.
+ */
+ private long stderrTimeout = 2000;
+
/** object used to ensure multiple threads don't try to expand same file */
static Object expandFileLock = new Object();
@@ -284,18 +289,11 @@
* interferes with the servlet's normal
* operation
*/
+ @Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
- // Verify that we were not accessed using the invoker servlet
- String servletName = getServletConfig().getServletName();
- if (servletName == null)
- servletName = "";
- if (servletName.startsWith("org.apache.catalina.INVOKER."))
- throw new UnavailableException
- ("Cannot invoke CGIServlet through the invoker");
-
// Set our properties from the initialization parameters
if (getServletConfig().getInitParameter("debug") != null)
debug = Integer.parseInt(getServletConfig().getInitParameter("debug"));
@@ -315,10 +313,14 @@
parameterEncoding = getServletConfig().getInitParameter("parameterEncoding");
}
+ if (getServletConfig().getInitParameter("stderrTimeout") != null) {
+ stderrTimeout = Long.parseLong(getServletConfig().getInitParameter(
+ "stderrTimeout"));
+ }
+
}
-
/**
* Prints out important Servlet API and container information
*
@@ -335,7 +337,9 @@
*
*/
protected void printServletEnvironment(ServletOutputStream out,
- HttpServletRequest req, HttpServletResponse res) throws IOException {
+ HttpServletRequest req,
+ @SuppressWarnings("unused") HttpServletResponse res)
+ throws IOException {
// Document the properties from ServletRequest
out.println("<h1>ServletRequest Properties</h1>");
@@ -521,11 +525,9 @@
out.println("<hr>");
-
}
-
/**
* Provides CGI Gateway service -- delegates to <code>doGet</code>
*
@@ -538,13 +540,13 @@
* @see javax.servlet.http.HttpServlet
*
*/
+ @Override
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
doGet(req, res);
}
-
/**
* Provides CGI Gateway service
*
@@ -557,6 +559,7 @@
* @see javax.servlet.http.HttpServlet
*
*/
+ @Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
@@ -620,13 +623,6 @@
} //doGet
-
- /** For future testing use only; does nothing right now */
- public static void main(String[] args) {
- System.out.println("$Header$");
- }
-
-
/**
* Encapsulates the CGI environment and rules to derive
* that environment from the servlet container and request information.
@@ -634,7 +630,7 @@
* <p>
* </p>
*
- * @version $Revision$, $Date$
+ * @version $Id$
* @since Tomcat 4.0
*
*/
@@ -700,7 +696,6 @@
}
-
/**
* Uses the ServletContext to set some CGI variables
*
@@ -714,7 +709,6 @@
}
-
/**
* Uses the HttpServletRequest to set most CGI variables
*
@@ -880,23 +874,23 @@
}
if (!currentLocation.isFile()) {
return new String[] { null, null, null, null };
- } else {
- if (debug >= 2) {
- log("findCGI: FOUND cgi at " + currentLocation);
- }
- path = currentLocation.getAbsolutePath();
- name = currentLocation.getName();
+ }
- if (".".equals(contextPath)) {
- scriptname = servletPath;
- } else {
- scriptname = contextPath + servletPath;
- }
- if (!servletPath.equals(cginame)) {
- scriptname = scriptname + cginame;
- }
+ if (debug >= 2) {
+ log("findCGI: FOUND cgi at " + currentLocation);
}
+ path = currentLocation.getAbsolutePath();
+ name = currentLocation.getName();
+ if (".".equals(contextPath)) {
+ scriptname = servletPath;
+ } else {
+ scriptname = contextPath + servletPath;
+ }
+ if (!servletPath.equals(cginame)) {
+ scriptname = scriptname + cginame;
+ }
+
if (debug >= 1) {
log("findCGI calc: name=" + name + ", path=" + path
+ ", scriptname=" + scriptname + ", cginame=" + cginame);
@@ -906,10 +900,10 @@
/**
* Constructs the CGI environment to be supplied to the invoked CGI
- * script; relies heavliy on Servlet API methods and findCGI
+ * script; relies heavily on Servlet API methods and findCGI
*
* @param req request associated with the CGI
- * invokation
+ * Invocation
*
* @return true if environment was set OK, false if there
* was a problem and no environment was set
@@ -1184,6 +1178,7 @@
* @return HTML string containing CGI environment info
*
*/
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -1241,7 +1236,6 @@
}
-
/**
* Gets derived command string
*
@@ -1253,7 +1247,6 @@
}
-
/**
* Gets derived CGI working directory
*
@@ -1265,7 +1258,6 @@
}
-
/**
* Gets derived CGI environment
*
@@ -1277,7 +1269,6 @@
}
-
/**
* Gets derived CGI query parameters
*
@@ -1289,7 +1280,6 @@
}
-
/**
* Gets validity status
*
@@ -1302,7 +1292,6 @@
}
-
/**
* Converts null strings to blank strings ("")
*
@@ -1315,7 +1304,6 @@
}
-
/**
* Converts null strings to another string
*
@@ -1330,7 +1318,6 @@
}
-
/**
* Converts blank strings to another string
*
@@ -1347,14 +1334,9 @@
}
-
} //class CGIEnvironment
-
-
-
-
/**
* Encapsulates the knowledge of how to run a CGI script, given the
* script's desired environment and (optionally) input/output streams
@@ -1368,7 +1350,7 @@
* <p>
*
* The CGI environment and settings are derived from the information
- * passed to the constuctor.
+ * passed to the constructor.
*
* </p>
* <p>
@@ -1377,7 +1359,7 @@
* and <code>setResponse</code> methods, respectively.
* </p>
*
- * @version $Revision$, $Date$
+ * @version $Id$
*/
protected class CGIRunner {
@@ -1404,8 +1386,6 @@
private boolean readyToRun = false;
-
-
/**
* Creates a CGIRunner and initializes its environment, working
* directory, and query parameters.
@@ -1418,7 +1398,7 @@
* @param env Hashtable with the desired script environment
* @param wd File with the script's desired working directory
* @param params ArrayList with the script's query command line
- * paramters as strings
+ * parameters as strings
*/
protected CGIRunner(String command, Hashtable<String,String> env,
File wd, ArrayList<String> params) {
@@ -1430,7 +1410,6 @@
}
-
/**
* Checks & sets ready status
*/
@@ -1447,7 +1426,6 @@
}
-
/**
* Gets ready status
*
@@ -1459,7 +1437,6 @@
}
-
/**
* Sets HttpServletResponse object used to set headers and send
* output to
@@ -1473,7 +1450,6 @@
}
-
/**
* Sets standard input to be passed on to the invoked cgi script
*
@@ -1486,7 +1462,6 @@
}
-
/**
* Converts a Hashtable to a String array by converting each
* key/value pair in the Hashtable to a String in the form
@@ -1513,7 +1488,6 @@
}
-
/**
* Executes a CGI script with the desired environment, current working
* directory, and input/output streams
@@ -1546,7 +1520,10 @@
* segments</u>:
* This implementation does not allow "<code>.</code>" and
* "<code>..</code>" in the the path, and such characters
- * will result in an IOException being thrown;
+ * will result in an IOException being thrown (this should
+ * never happen since Tomcat normalises the requestURI
+ * before determining the contextPath, servletPath and
+ * pathInfo);
* <LI> <u>Implementation limitations</u>: This implementation
* does not impose any limitations except as documented
* above. This implementation may be limited by the
@@ -1588,50 +1565,32 @@
}
/* original content/structure of this section taken from
- * http://developer.java.sun.com/developer/
- * bugParade/bugs/4216884.html
+ * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4216884
* with major modifications by Martin Dengler
*/
Runtime rt = null;
BufferedReader cgiHeaderReader = null;
InputStream cgiOutput = null;
BufferedReader commandsStdErr = null;
+ Thread errReaderThread = null;
BufferedOutputStream commandsStdIn = null;
Process proc = null;
int bufRead = -1;
- //create query arguments
- StringBuilder cmdAndArgs = new StringBuilder();
- if (command.indexOf(" ") < 0) {
- cmdAndArgs.append(command);
- } else {
- // Spaces used as delimiter, so need to use quotes
- cmdAndArgs.append("\"");
- cmdAndArgs.append(command);
- cmdAndArgs.append("\"");
- }
+ String[] cmdAndArgs = new String[params.size() + 2];
+
+ cmdAndArgs[0] = cgiExecutable;
+
+ cmdAndArgs[1] = command;
+ //create query arguments
for (int i=0; i < params.size(); i++) {
- cmdAndArgs.append(" ");
- String param = params.get(i);
- if (param.indexOf(" ") < 0) {
- cmdAndArgs.append(param);
- } else {
- // Spaces used as delimiter, so need to use quotes
- cmdAndArgs.append("\"");
- cmdAndArgs.append(param);
- cmdAndArgs.append("\"");
- }
+ cmdAndArgs[i + 2] = params.get(i);
}
- StringBuilder command = new StringBuilder(cgiExecutable);
- command.append(" ");
- command.append(cmdAndArgs.toString());
- cmdAndArgs = command;
-
try {
rt = Runtime.getRuntime();
- proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd);
+ proc = rt.exec(cmdAndArgs, hashToStringArray(env), wd);
String sContentLength = env.get("CONTENT_LENGTH");
@@ -1644,8 +1603,7 @@
/* we want to wait for the process to exit, Process.waitFor()
* is useless in our situation; see
- * http://developer.java.sun.com/developer/
- * bugParade/bugs/4223650.html
+ * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4223650
*/
boolean isRunning = true;
@@ -1653,11 +1611,13 @@
(new InputStreamReader(proc.getErrorStream()));
final BufferedReader stdErrRdr = commandsStdErr ;
- new Thread() {
+ errReaderThread = new Thread() {
+ @Override
public void run () {
sendToLog(stdErrRdr) ;
}
- }.start() ;
+ };
+ errReaderThread.start();
InputStream cgiHeaderStream =
new HTTPHeaderInputStream(proc.getInputStream());
@@ -1709,7 +1669,9 @@
// such as a socket disconnect on the servlet side; otherwise, the
// external process could hang
if (bufRead != -1) {
- while ((bufRead = cgiOutput.read(bBuf)) != -1) {}
+ while ((bufRead = cgiOutput.read(bBuf)) != -1) {
+ // NOOP - just read the data
+ }
}
}
@@ -1721,6 +1683,7 @@
try {
Thread.sleep(500);
} catch (InterruptedException ignored) {
+ // Ignore
}
}
} //replacement for Process.waitFor()
@@ -1747,6 +1710,14 @@
log ("Exception closing output stream " + ioe);
}
}
+ // Make sure the error stream reader has finished
+ if (errReaderThread != null) {
+ try {
+ errReaderThread.join(stderrTimeout);
+ } catch (InterruptedException e) {
+ log ("Interupted waiting for stderr reader thread");
+ }
+ }
if (debug > 4) {
log ("Running finally block");
}
@@ -1862,6 +1833,7 @@
/**
* @see java.io.InputStream#read()
*/
+ @Override
public int read() throws IOException {
if (state == STATE_HEADER_END) {
return -1;
14 years, 10 months
JBossWeb SVN: r1583 - trunk/java/org/apache/catalina/filters.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2010-11-23 05:13:25 -0500 (Tue, 23 Nov 2010)
New Revision: 1583
Modified:
trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java
Log:
- CSRF update.
Modified: trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java
===================================================================
--- trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java 2010-11-23 09:44:33 UTC (rev 1582)
+++ trunk/java/org/apache/catalina/filters/CsrfPreventionFilter.java 2010-11-23 10:13:25 UTC (rev 1583)
@@ -117,6 +117,7 @@
}
}
+ @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
@@ -204,7 +205,7 @@
return buffer.toString();
}
- private static class CsrfResponseWrapper
+ protected static class CsrfResponseWrapper
extends HttpServletResponseWrapper {
private String nonce;
@@ -237,7 +238,7 @@
}
/**
- * Return the specified URL with the nonce added to the query string
+ * Return the specified URL with the nonce added to the query string.
*
* @param url URL to be modified
* @param nonce The nonce to add
@@ -250,18 +251,17 @@
String path = url;
String query = "";
String anchor = "";
- int question = url.indexOf('?');
- if (question >= 0) {
- path = url.substring(0, question);
- query = url.substring(question);
- }
int pound = path.indexOf('#');
if (pound >= 0) {
anchor = path.substring(pound);
path = path.substring(0, pound);
}
+ int question = path.indexOf('?');
+ if (question >= 0) {
+ query = path.substring(question);
+ path = path.substring(0, question);
+ }
StringBuilder sb = new StringBuilder(path);
- sb.append(anchor);
if (query.length() >0) {
sb.append(query);
sb.append('&');
@@ -271,6 +271,7 @@
sb.append(Constants.CSRF_NONCE_REQUEST_PARAM);
sb.append('=');
sb.append(nonce);
+ sb.append(anchor);
return (sb.toString());
}
}
14 years, 10 months
JBossWeb SVN: r1582 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2010-11-23 04:44:33 -0500 (Tue, 23 Nov 2010)
New Revision: 1582
Modified:
trunk/java/org/apache/jasper/compiler/Compiler.java
trunk/webapps/docs/changelog.xml
Log:
- 49726: Default content type should not override.
Modified: trunk/java/org/apache/jasper/compiler/Compiler.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Compiler.java 2010-11-23 09:34:25 UTC (rev 1581)
+++ trunk/java/org/apache/jasper/compiler/Compiler.java 2010-11-23 09:44:33 UTC (rev 1582)
@@ -139,9 +139,7 @@
pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty
.isTrimDirectiveWhitespaces()));
}
- if (jspProperty.getDefaultContentType() != null && pageInfo.getContentType() == null) {
- pageInfo.setContentType(jspProperty.getDefaultContentType());
- }
+ // Default ContentType processing is deferred until after the page has been parsed
if (jspProperty.getBuffer() != null && pageInfo.getBufferValue() == null) {
pageInfo.setBufferValue(jspProperty.getBuffer(), errDispatcher);
}
@@ -195,6 +193,10 @@
// Pass 2 - the whole translation unit
pageNodes = parserCtl.parse(ctxt.getJspFile());
+ if (jspProperty.getDefaultContentType() != null && pageInfo.getContentType() == null) {
+ pageInfo.setContentType(jspProperty.getDefaultContentType());
+ }
+
if (ctxt.isPrototypeMode()) {
// generate prototype .java file for the tag file
writer = setupContextWriter(javaFileName);
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2010-11-23 09:34:25 UTC (rev 1581)
+++ trunk/webapps/docs/changelog.xml 2010-11-23 09:44:33 UTC (rev 1582)
@@ -49,6 +49,10 @@
<fix>
<bug>49555</bug>: Fix use of static inner classes in taglibs. (markt)
</fix>
+ <fix>
+ <bug>49726</bug>: Specifying a default content type via a JSP property group
+ should not prevent a page from setting some other content type. (markt)
+ </fix>
</changelog>
</subsection>
</section>
14 years, 10 months
JBossWeb SVN: r1581 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2010-11-23 04:34:25 -0500 (Tue, 23 Nov 2010)
New Revision: 1581
Modified:
trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java
trunk/webapps/docs/changelog.xml
Log:
- 49779: Interaction between continue and FORM.
Modified: trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java
===================================================================
--- trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java 2010-11-23 09:27:56 UTC (rev 1580)
+++ trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java 2010-11-23 09:34:25 UTC (rev 1581)
@@ -243,8 +243,9 @@
return (false);
}
- // Yes -- Validate the specified credentials and redirect
- // to the error page if they are not correct
+ // Yes -- Acknowledge the request, validate the specified credentials
+ // and redirect to the error page if they are not correct
+ request.getResponse().sendAcknowledgement();
Realm realm = context.getRealm();
if (characterEncoding != null) {
request.setCharacterEncoding(characterEncoding);
@@ -440,6 +441,13 @@
request.getCoyoteRequest().getParameters().setQueryStringEncoding(request.getConnector().getURIEncoding());
+ // Swallow any request body since we will be replacing it
+ byte[] buffer = new byte[4096];
+ InputStream is = request.getInputStream();
+ while (is.read(buffer) >= 0) {
+ // Ignore request body
+ }
+
if ("POST".equalsIgnoreCase(saved.getMethod())) {
ByteChunk body = saved.getBody();
@@ -516,6 +524,8 @@
}
if ("POST".equalsIgnoreCase(request.getMethod())) {
+ // May need to acknowledge a 100-continue expectation
+ request.getResponse().sendAcknowledgement();
ByteChunk body = new ByteChunk();
body.setLimit(request.getConnector().getMaxSavePostSize());
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2010-11-23 09:27:56 UTC (rev 1580)
+++ trunk/webapps/docs/changelog.xml 2010-11-23 09:34:25 UTC (rev 1581)
@@ -28,6 +28,9 @@
<fix>
Improve session id creation. (remm)
</fix>
+ <fix>
+ <bug>49779</bug>: Interaction between continue and FORM. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
14 years, 10 months
JBossWeb SVN: r1580 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2010-11-23 04:27:56 -0500 (Tue, 23 Nov 2010)
New Revision: 1580
Modified:
trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java
trunk/webapps/docs/changelog.xml
Log:
- 49555: Fix use of static inner classes in taglibs.
Modified: trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java 2010-11-19 16:06:19 UTC (rev 1579)
+++ trunk/java/org/apache/jasper/compiler/ELFunctionMapper.java 2010-11-23 09:27:56 UTC (rev 1580)
@@ -17,8 +17,12 @@
package org.apache.jasper.compiler;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.*;
import javax.servlet.jsp.tagext.FunctionInfo;
+
+import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
/**
@@ -201,9 +205,9 @@
FunctionInfo funcInfo = f.getFunctionInfo();
String key = f.getPrefix()+ ":" + f.getName();
ds.append(funcMethod + "(\"" + key + "\", " +
- funcInfo.getFunctionClass() + ".class, " +
- '\"' + f.getMethodName() + "\", " +
- "new Class[] {");
+ getCanonicalName(funcInfo.getFunctionClass()) +
+ ".class, " + '\"' + f.getMethodName() + "\", " +
+ "new Class[] {");
String params[] = f.getParameters();
for (int k = 0; k < params.length; k++) {
if (k != 0) {
@@ -241,7 +245,42 @@
el.setMapName(decName);
}
- /**
+ /**
+ * Convert a binary class name into a canonical one that can be used
+ * when generating Java source code.
+ *
+ * @param className Binary class name
+ * @return Canonical equivalent
+ */
+ private String getCanonicalName(String className) throws JasperException {
+ Class<?> clazz;
+
+ ClassLoader tccl;
+ if (Constants.IS_SECURITY_ENABLED) {
+ PrivilegedAction<ClassLoader> pa = new PrivilegedGetTccl();
+ tccl = AccessController.doPrivileged(pa);
+ } else {
+ tccl = Thread.currentThread().getContextClassLoader();
+ }
+
+ try {
+ clazz = Class.forName(className, true, tccl);
+ } catch (ClassNotFoundException e) {
+ throw new JasperException(e);
+ }
+ return clazz.getCanonicalName();
+ }
+ }
+
+ private static class PrivilegedGetTccl
+ implements PrivilegedAction<ClassLoader> {
+
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+
+ /**
* Find the name of the function mapper for an EL. Reuse a
* previously generated one if possible.
* @param functions An ArrayList of ELNode.Function instances that
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2010-11-19 16:06:19 UTC (rev 1579)
+++ trunk/webapps/docs/changelog.xml 2010-11-23 09:27:56 UTC (rev 1580)
@@ -43,6 +43,9 @@
<bug>50192</bug>: Fix regression getting the EL resolver. Tighter security can
be enabled back. (remm)
</fix>
+ <fix>
+ <bug>49555</bug>: Fix use of static inner classes in taglibs. (markt)
+ </fix>
</changelog>
</subsection>
</section>
14 years, 10 months
JBossWeb SVN: r1579 - in trunk: java/org/apache/catalina/authenticator and 5 other directories.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2010-11-19 11:06:19 -0500 (Fri, 19 Nov 2010)
New Revision: 1579
Modified:
trunk/java/org/apache/catalina/Manager.java
trunk/java/org/apache/catalina/Service.java
trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
trunk/java/org/apache/catalina/connector/Request.java
trunk/java/org/apache/catalina/core/ApplicationHttpRequest.java
trunk/java/org/apache/catalina/core/StandardService.java
trunk/java/org/apache/catalina/session/ManagerBase.java
trunk/java/org/apache/catalina/session/PersistentManagerBase.java
trunk/java/org/apache/catalina/session/StandardManager.java
trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
trunk/webapps/docs/changelog.xml
Log:
- Improve session id creation.
- Add a master SecureRandom in Service.
- Add local SecureRandom providers seeded with the master SecureRandom in the Request.
- Port session id hashing and alphabet from AS 6 (which will need a little refactoring).
Modified: trunk/java/org/apache/catalina/Manager.java
===================================================================
--- trunk/java/org/apache/catalina/Manager.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/Manager.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -21,6 +21,7 @@
import java.beans.PropertyChangeListener;
import java.io.IOException;
+import java.util.Random;
/**
@@ -265,7 +266,7 @@
*
* @param session The session to change the session ID for
*/
- public void changeSessionId(Session session);
+ public void changeSessionId(Session session, Random random);
/**
@@ -279,20 +280,6 @@
/**
* Construct and return a new session object, based on the default
* settings specified by this Manager's properties. The session
- * id will be assigned by this method, and available via the getId()
- * method of the returned session. If a new session cannot be created
- * for any reason, return <code>null</code>.
- *
- * @exception IllegalStateException if a new session cannot be
- * instantiated for any reason
- * @deprecated
- */
- public Session createSession();
-
-
- /**
- * Construct and return a new session object, based on the default
- * settings specified by this Manager's properties. The session
* id specified will be used as the session id.
* If a new session cannot be created for any reason, return
* <code>null</code>.
@@ -304,7 +291,7 @@
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
*/
- public Session createSession(String sessionId);
+ public Session createSession(String sessionId, Random random);
/**
Modified: trunk/java/org/apache/catalina/Service.java
===================================================================
--- trunk/java/org/apache/catalina/Service.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/Service.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -18,6 +18,8 @@
package org.apache.catalina;
+import java.security.SecureRandom;
+
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.http.mapper.Mapper;
@@ -80,6 +82,19 @@
public void setName(String name);
/**
+ * Return the entropy increaser value, or compute a semi-useful value
+ * if this String has not yet been set.
+ */
+ public String getEntropy();
+
+ /**
+ * Set the entropy increaser value.
+ *
+ * @param entropy The new entropy increaser value
+ */
+ public void setEntropy(String entropy);
+
+ /**
* Return the <code>Server</code> with which we are associated (if any).
*/
public Server getServer();
@@ -149,4 +164,9 @@
*/
public void removeExecutor(Executor ex);
+ /**
+ * Get the global secure random that will be used for this service.
+ */
+ public SecureRandom getRandom();
+
}
Modified: trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
===================================================================
--- trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -784,7 +784,7 @@
Session session = request.getSessionInternal(false);
if (session != null && changeSessionIdOnAuthentication) {
Manager manager = request.getContext().getManager();
- manager.changeSessionId(session);
+ manager.changeSessionId(session, request.getRandom());
request.changeSessionId(session.getId());
}
// Cache the authentication information in our session, if any
Modified: trunk/java/org/apache/catalina/connector/Request.java
===================================================================
--- trunk/java/org/apache/catalina/connector/Request.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/connector/Request.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -53,6 +53,7 @@
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
+import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -64,6 +65,7 @@
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.Random;
import java.util.TimeZone;
import java.util.TreeMap;
@@ -168,7 +170,7 @@
formats[0].setTimeZone(GMT_ZONE);
formats[1].setTimeZone(GMT_ZONE);
formats[2].setTimeZone(GMT_ZONE);
-
+
}
@@ -479,6 +481,12 @@
protected boolean sslAttributes = false;
+ /**
+ * Random generator.
+ */
+ protected Random random = null;
+
+
// --------------------------------------------------------- Public Methods
@@ -622,6 +630,10 @@
*/
public void setConnector(Connector connector) {
this.connector = connector;
+ SecureRandom seedRandom = connector.getService().getRandom();
+ synchronized (seedRandom) {
+ random = new SecureRandom(seedRandom.generateSeed(16));
+ }
}
@@ -652,6 +664,13 @@
/**
+ * Return the Random.
+ */
+ public Random getRandom() {
+ return (this.random);
+ }
+
+ /**
* Filter chains associated with the request.
*/
protected ArrayList<ApplicationFilterChain> filterChains = new ArrayList<ApplicationFilterChain>();
@@ -2603,7 +2622,7 @@
sessionId = null;
}
}
- session = manager.createSession(sessionId);
+ session = manager.createSession(sessionId, random);
// Creating a new session cookie based on that session
// If there was no cookie with the current session id, add a cookie to the response
Modified: trunk/java/org/apache/catalina/core/ApplicationHttpRequest.java
===================================================================
--- trunk/java/org/apache/catalina/core/ApplicationHttpRequest.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/core/ApplicationHttpRequest.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -556,7 +556,7 @@
localSession = null;
if (localSession == null && create) {
localSession =
- context.getManager().createSession(other.getId());
+ context.getManager().createSession(other.getId(), null);
}
if (localSession != null) {
localSession.access();
Modified: trunk/java/org/apache/catalina/core/StandardService.java
===================================================================
--- trunk/java/org/apache/catalina/core/StandardService.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/core/StandardService.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -21,6 +21,8 @@
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
+import java.lang.reflect.Method;
+import java.security.SecureRandom;
import java.util.ArrayList;
import javax.management.MBeanRegistration;
@@ -36,6 +38,7 @@
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
+import org.apache.catalina.util.Base64;
import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.util.StringManager;
import org.apache.tomcat.util.http.mapper.Mapper;
@@ -145,6 +148,19 @@
protected boolean initialized = false;
+ /**
+ * A String initialization parameter used to increase the entropy of
+ * the initialization of our random number generator.
+ */
+ protected String entropy = null;
+
+
+ /**
+ * The random associated with this service.
+ */
+ protected SecureRandom random = null;
+
+
// ------------------------------------------------------------- Properties
@@ -269,9 +285,53 @@
}
+ @Override
+ public String getEntropy() {
+ // Calculate a semi-useful value if this has not been set
+ if (this.entropy == null) {
+ // Use APR to get a crypto secure entropy value
+ byte[] result = new byte[32];
+ boolean apr = false;
+ try {
+ String methodName = "random";
+ Class paramTypes[] = new Class[2];
+ paramTypes[0] = result.getClass();
+ paramTypes[1] = int.class;
+ Object paramValues[] = new Object[2];
+ paramValues[0] = result;
+ paramValues[1] = new Integer(32);
+ Method method = Class.forName("org.apache.tomcat.jni.OS")
+ .getMethod(methodName, paramTypes);
+ method.invoke(null, paramValues);
+ apr = true;
+ } catch (Throwable t) {
+ // Ignore
+ }
+ if (apr) {
+ setEntropy(new String(Base64.encode(result)));
+ } else {
+ setEntropy(this.toString());
+ }
+ }
+ return (this.entropy);
+ }
+
+
+ @Override
+ public void setEntropy(String entropy) {
+ this.entropy = entropy;
+ }
+
+
// --------------------------------------------------------- Public Methods
+ @Override
+ public SecureRandom getRandom() {
+ return random;
+ }
+
+
/**
* Add a new Connector to the set of defined Connectors, and associate it
* with this Service's Container.
@@ -697,10 +757,13 @@
// Initialize our defined Connectors
synchronized (connectors) {
- for (int i = 0; i < connectors.length; i++) {
- connectors[i].initialize();
- }
+ for (int i = 0; i < connectors.length; i++) {
+ connectors[i].initialize();
+ }
}
+
+ // Construct and seed a new random number generator
+ random = new SecureRandom(getEntropy().getBytes());
}
public void destroy() throws LifecycleException {
@@ -749,4 +812,5 @@
public void postDeregister() {
}
+
}
Modified: trunk/java/org/apache/catalina/session/ManagerBase.java
===================================================================
--- trunk/java/org/apache/catalina/session/ManagerBase.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/session/ManagerBase.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -21,15 +21,7 @@
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
-import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivilegedAction;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@@ -44,16 +36,13 @@
import org.apache.catalina.Container;
import org.apache.catalina.Engine;
-import org.apache.catalina.Globals;
import org.apache.catalina.Manager;
import org.apache.catalina.Session;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
-import org.apache.catalina.util.Base64;
import org.apache.catalina.util.StringManager;
import org.apache.tomcat.util.modeler.Registry;
import org.jboss.logging.Logger;
-import org.jboss.logging.Logger;
/**
@@ -68,40 +57,19 @@
public abstract class ManagerBase implements Manager, MBeanRegistration {
protected Logger log = Logger.getLogger(ManagerBase.class);
- // ----------------------------------------------------- Instance Variables
+ private static final char[] SESSION_ID_ALPHABET =
+ System.getProperty("org.apache.catalina.session.ManagerBase.SESSION_ID_ALPHABET",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_").toCharArray();
+
+ // ----------------------------------------------------- Instance Variables
- protected DataInputStream randomIS=null;
- protected String devRandomSource="/dev/urandom";
-
/**
- * The default message digest algorithm to use if we cannot use
- * the requested one.
- */
- protected static final String DEFAULT_ALGORITHM = "MD5";
-
-
- /**
- * The message digest algorithm to be used when generating session
- * identifiers. This must be an algorithm supported by the
- * <code>java.security.MessageDigest</code> class on your platform.
- */
- protected String algorithm = DEFAULT_ALGORITHM;
-
-
- /**
* The Container with which this Manager is associated.
*/
protected Container container;
/**
- * Return the MessageDigest implementation to be used when
- * creating session identifiers.
- */
- protected MessageDigest digest = null;
-
-
- /**
* The distributable flag for Sessions created by this Manager. If this
* flag is set to <code>true</code>, any user attributes added to a
* session controlled by this Manager must be Serializable.
@@ -110,16 +78,9 @@
/**
- * A String initialization parameter used to increase the entropy of
- * the initialization of our random number generator.
- */
- protected String entropy = null;
-
-
- /**
* The descriptive information string for this implementation.
*/
- private static final String info = "ManagerBase/1.0";
+ private static final String info = "ManagerBase/2.0";
/**
@@ -132,7 +93,7 @@
/**
* The session id length of Sessions created by this Manager.
*/
- protected int sessionIdLength = 16;
+ protected int sessionIdLength = 18;
/**
@@ -142,19 +103,6 @@
/**
- * A random number generator to use when generating session identifiers.
- */
- protected Random random = null;
-
-
- /**
- * The Java class name of the random number generator class to be used
- * when generating session identifiers.
- */
- protected String randomClass = "java.security.SecureRandom";
-
-
- /**
* The longest time (in seconds) that an expired session had been alive.
*/
protected int sessionMaxAliveTime;
@@ -219,68 +167,9 @@
protected PropertyChangeSupport support = new PropertyChangeSupport(this);
- // ------------------------------------------------------------- Security classes
-
-
- private class PrivilegedSetRandomFile implements PrivilegedAction<DataInputStream>{
-
- public PrivilegedSetRandomFile(String s) {
- devRandomSource = s;
- }
-
- public DataInputStream run(){
- try {
- File f=new File( devRandomSource );
- if( ! f.exists() ) return null;
- randomIS= new DataInputStream( new FileInputStream(f));
- randomIS.readLong();
- if( log.isDebugEnabled() )
- log.debug( "Opening " + devRandomSource );
- return randomIS;
- } catch (IOException ex){
- log.warn("Error reading " + devRandomSource, ex);
- if (randomIS != null) {
- try {
- randomIS.close();
- } catch (Exception e) {
- log.warn("Failed to close randomIS.");
- }
- }
- devRandomSource = null;
- randomIS=null;
- return null;
- }
- }
- }
-
-
// ------------------------------------------------------------- Properties
/**
- * Return the message digest algorithm for this Manager.
- */
- public String getAlgorithm() {
-
- return (this.algorithm);
-
- }
-
-
- /**
- * Set the message digest algorithm for this Manager.
- *
- * @param algorithm The new message digest algorithm
- */
- public void setAlgorithm(String algorithm) {
-
- String oldAlgorithm = this.algorithm;
- this.algorithm = algorithm;
- support.firePropertyChange("algorithm", oldAlgorithm, this.algorithm);
-
- }
-
-
- /**
* Return the Container with which this Manager is associated.
*/
public Container getContainer() {
@@ -311,41 +200,6 @@
/**
- * Return the MessageDigest object to be used for calculating
- * session identifiers. If none has been created yet, initialize
- * one the first time this method is called.
- */
- public synchronized MessageDigest getDigest() {
-
- if (this.digest == null) {
- long t1=System.currentTimeMillis();
- if (log.isDebugEnabled())
- log.debug(sm.getString("managerBase.getting", algorithm));
- try {
- this.digest = MessageDigest.getInstance(algorithm);
- } catch (NoSuchAlgorithmException e) {
- log.error(sm.getString("managerBase.digest", algorithm), e);
- try {
- this.digest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
- } catch (NoSuchAlgorithmException f) {
- log.error(sm.getString("managerBase.digest",
- DEFAULT_ALGORITHM), e);
- this.digest = null;
- }
- }
- if (log.isDebugEnabled())
- log.debug(sm.getString("managerBase.gotten"));
- long t2=System.currentTimeMillis();
- if( log.isDebugEnabled() )
- log.debug("getDigest() " + (t2-t1));
- }
-
- return (this.digest);
-
- }
-
-
- /**
* Return the distributable flag for the sessions supported by
* this Manager.
*/
@@ -375,58 +229,6 @@
/**
- * Return the entropy increaser value, or compute a semi-useful value
- * if this String has not yet been set.
- */
- public String getEntropy() {
-
- // Calculate a semi-useful value if this has not been set
- if (this.entropy == null) {
- // Use APR to get a crypto secure entropy value
- byte[] result = new byte[32];
- boolean apr = false;
- try {
- String methodName = "random";
- Class paramTypes[] = new Class[2];
- paramTypes[0] = result.getClass();
- paramTypes[1] = int.class;
- Object paramValues[] = new Object[2];
- paramValues[0] = result;
- paramValues[1] = new Integer(32);
- Method method = Class.forName("org.apache.tomcat.jni.OS")
- .getMethod(methodName, paramTypes);
- method.invoke(null, paramValues);
- apr = true;
- } catch (Throwable t) {
- // Ignore
- }
- if (apr) {
- setEntropy(new String(Base64.encode(result)));
- } else {
- setEntropy(this.toString());
- }
- }
-
- return (this.entropy);
-
- }
-
-
- /**
- * Set the entropy increaser value.
- *
- * @param entropy The new entropy increaser value
- */
- public void setEntropy(String entropy) {
-
- String oldEntropy = entropy;
- this.entropy = entropy;
- support.firePropertyChange("entropy", oldEntropy, this.entropy);
-
- }
-
-
- /**
* Return descriptive information about this Manager implementation and
* the corresponding version number, in the format
* <code><description>/<version></code>.
@@ -505,110 +307,7 @@
}
- /**
- * Use /dev/random-type special device. This is new code, but may reduce
- * the big delay in generating the random.
- *
- * You must specify a path to a random generator file. Use /dev/urandom
- * for linux ( or similar ) systems. Use /dev/random for maximum security
- * ( it may block if not enough "random" exist ). You can also use
- * a pipe that generates random.
- *
- * The code will check if the file exists, and default to java Random
- * if not found. There is a significant performance difference, very
- * visible on the first call to getSession ( like in the first JSP )
- * - so use it if available.
- */
- public void setRandomFile( String s ) {
- // as a hack, you can use a static file - and generate the same
- // session ids ( good for strange debugging )
- if (Globals.IS_SECURITY_ENABLED){
- randomIS = AccessController.doPrivileged(new PrivilegedSetRandomFile(s));
- } else {
- try{
- devRandomSource=s;
- File f=new File( devRandomSource );
- if( ! f.exists() ) return;
- randomIS= new DataInputStream( new FileInputStream(f));
- randomIS.readLong();
- if( log.isDebugEnabled() )
- log.debug( "Opening " + devRandomSource );
- } catch( IOException ex ) {
- log.warn("Error reading " + devRandomSource, ex);
- if (randomIS != null) {
- try {
- randomIS.close();
- } catch (Exception e) {
- log.warn("Failed to close randomIS.");
- }
- }
- devRandomSource = null;
- randomIS=null;
- }
- }
- }
-
- public String getRandomFile() {
- return devRandomSource;
- }
-
-
/**
- * Return the random number generator instance we should use for
- * generating session identifiers. If there is no such generator
- * currently defined, construct and seed a new one.
- */
- public Random getRandom() {
- if (this.random == null) {
- // Calculate the new random number generator seed
- long seed = System.nanoTime();
- char entropy[] = getEntropy().toCharArray();
- for (int i = 0; i < entropy.length; i++) {
- long update = ((byte) entropy[i]) << ((i % 8) * 8);
- seed ^= update;
- }
- // Construct and seed a new random number generator
- try {
- Class clazz = Class.forName(randomClass);
- this.random = (Random) clazz.newInstance();
- } catch (Exception e) {
- log.warn(sm.getString("managerBase.random", randomClass), e);
- this.random = new java.util.Random();
- }
- this.random.setSeed(seed);
- }
-
- return (this.random);
-
- }
-
-
- /**
- * Return the random number generator class name.
- */
- public String getRandomClass() {
-
- return (this.randomClass);
-
- }
-
-
- /**
- * Set the random number generator class name.
- *
- * @param randomClass The new random number generator class name
- */
- public void setRandomClass(String randomClass) {
-
- String oldRandomClass = this.randomClass;
- this.randomClass = randomClass;
- support.firePropertyChange("randomClass", oldRandomClass,
- this.randomClass);
-
- }
-
-
- /**
* Gets the number of sessions that have expired.
*
* @return Number of sessions that have expired
@@ -702,14 +401,6 @@
public void destroy() {
if( oname != null )
Registry.getRegistry(null, null).unregisterComponent(oname);
- if (randomIS!=null) {
- try {
- randomIS.close();
- } catch (IOException ioe) {
- log.warn("Failed to close randomIS.");
- }
- randomIS=null;
- }
initialized=false;
oname = null;
}
@@ -739,9 +430,6 @@
}
}
- // Initialize random number generation
- getRandomBytes(new byte[16]);
-
if(log.isDebugEnabled())
log.debug("Registering " + oname );
@@ -780,30 +468,14 @@
*
* @param session The session to change the session ID for
*/
- public void changeSessionId(Session session) {
- session.setId(generateSessionId());
+ public void changeSessionId(Session session, Random random) {
+ session.setId(generateSessionId(random));
}
/**
* Construct and return a new session object, based on the default
* settings specified by this Manager's properties. The session
- * id will be assigned by this method, and available via the getId()
- * method of the returned session. If a new session cannot be created
- * for any reason, return <code>null</code>.
- *
- * @exception IllegalStateException if a new session cannot be
- * instantiated for any reason
- * @deprecated
- */
- public Session createSession() {
- return createSession(null);
- }
-
-
- /**
- * Construct and return a new session object, based on the default
- * settings specified by this Manager's properties. The session
* id specified will be used as the session id.
* If a new session cannot be created for any reason, return
* <code>null</code>.
@@ -814,7 +486,7 @@
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
*/
- public Session createSession(String sessionId) {
+ public Session createSession(String sessionId, Random random) {
// Recycle or create a Session instance
Session session = createEmptySession();
@@ -825,34 +497,7 @@
session.setCreationTime(System.currentTimeMillis());
session.setMaxInactiveInterval(this.maxInactiveInterval);
if (sessionId == null) {
- sessionId = generateSessionId();
- // FIXME WHy we need no duplication check?
- /*
- synchronized (sessions) {
- while (sessions.get(sessionId) != null) { // Guarantee
- // uniqueness
- duplicates++;
- sessionId = generateSessionId();
- }
- }
- */
-
- // FIXME: Code to be used in case route replacement is needed
- /*
- } else {
- String jvmRoute = getJvmRoute();
- if (getJvmRoute() != null) {
- String requestJvmRoute = null;
- int index = sessionId.indexOf(".");
- if (index > 0) {
- requestJvmRoute = sessionId
- .substring(index + 1, sessionId.length());
- }
- if (requestJvmRoute != null && !requestJvmRoute.equals(jvmRoute)) {
- sessionId = sessionId.substring(0, index) + "." + jvmRoute;
- }
- }
- */
+ sessionId = generateSessionId(random);
}
session.setId(sessionId);
sessionCounter++;
@@ -938,83 +583,70 @@
}
- protected void getRandomBytes(byte bytes[]) {
- // Generate a byte array containing a session identifier
- if (devRandomSource != null && randomIS == null) {
- setRandomFile(devRandomSource);
+ /**
+ * Generate and return a new session identifier.
+ */
+ protected String generateSessionId(Random random) {
+ byte[] bytes = new byte[sessionIdLength];
+ random.nextBytes(bytes);
+ // Encode the result
+ char[] id = encode(bytes);
+ String jvmRoute = getJvmRoute();
+ if (appendJVMRoute() && jvmRoute != null) {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append(id).append('.').append(jvmRoute);
+ return buffer.toString();
+ } else {
+ return String.valueOf(id);
}
- if (randomIS != null) {
- try {
- int len = randomIS.read(bytes);
- if (len == bytes.length) {
- return;
- }
- if(log.isDebugEnabled())
- log.debug("Got " + len + " " + bytes.length );
- } catch (Exception ex) {
- // Ignore
- }
- devRandomSource = null;
-
- try {
- randomIS.close();
- } catch (Exception e) {
- log.warn("Failed to close randomIS.");
- }
-
- randomIS = null;
- }
- getRandom().nextBytes(bytes);
}
-
+ protected boolean appendJVMRoute() {
+ return true;
+ }
+
/**
- * Generate and return a new session identifier.
+ * Encode the bytes into a String with a slightly modified Base64-algorithm
+ * This code was written by Kevin Kelley <kelley(a)ruralnet.net>
+ * and adapted by Thomas Peuss <jboss(a)peuss.de>
+ *
+ * @param data The bytes you want to encode
+ * @return the encoded String
*/
- protected synchronized String generateSessionId() {
+ protected static char[] encode(byte[] data) {
+ char[] out = new char[((data.length + 2) / 3) * 4];
+ char[] alphabet = SESSION_ID_ALPHABET;
+ //
+ // 3 bytes encode to 4 chars. Output is always an even
+ // multiple of 4 characters.
+ //
+ for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
+ boolean quad = false;
+ boolean trip = false;
- byte random[] = new byte[16];
- String jvmRoute = getJvmRoute();
- String result = null;
-
- // Render the result as a String of hexadecimal digits
- StringBuilder buffer = new StringBuilder();
- do {
- int resultLenBytes = 0;
- if (result != null) {
- buffer = new StringBuilder();
- duplicates++;
- }
-
- while (resultLenBytes < this.sessionIdLength) {
- getRandomBytes(random);
- random = getDigest().digest(random);
- for (int j = 0;
- j < random.length && resultLenBytes < this.sessionIdLength;
- j++) {
- byte b1 = (byte) ((random[j] & 0xf0) >> 4);
- byte b2 = (byte) (random[j] & 0x0f);
- if (b1 < 10)
- buffer.append((char) ('0' + b1));
- else
- buffer.append((char) ('A' + (b1 - 10)));
- if (b2 < 10)
- buffer.append((char) ('0' + b2));
- else
- buffer.append((char) ('A' + (b2 - 10)));
- resultLenBytes++;
- }
- }
- if (jvmRoute != null) {
- buffer.append('.').append(jvmRoute);
- }
- result = buffer.toString();
- } while (sessions.containsKey(result));
- return (result);
-
+ int val = (0xFF & (int) data[i]);
+ val <<= 8;
+ if ((i + 1) < data.length) {
+ val |= (0xFF & (int) data[i + 1]);
+ trip = true;
+ }
+ val <<= 8;
+ if ((i + 2) < data.length) {
+ val |= (0xFF & (int) data[i + 2]);
+ quad = true;
+ }
+ out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
+ val >>= 6;
+ out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
+ val >>= 6;
+ out[index + 1] = alphabet[val & 0x3F];
+ val >>= 6;
+ out[index + 0] = alphabet[val & 0x3F];
+ }
+ return out;
}
-
+
// ------------------------------------------------------ Protected Methods
Modified: trunk/java/org/apache/catalina/session/PersistentManagerBase.java
===================================================================
--- trunk/java/org/apache/catalina/session/PersistentManagerBase.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/session/PersistentManagerBase.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -34,11 +34,9 @@
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Session;
import org.apache.catalina.Store;
-import org.apache.catalina.util.LifecycleSupport;
-
import org.apache.catalina.security.SecurityUtil;
+import org.apache.catalina.util.LifecycleSupport;
import org.jboss.logging.Logger;
-import org.jboss.logging.Logger;
/**
* Extends the <b>ManagerBase</b> class to implement most of the
* functionality required by a Manager which supports any kind of
@@ -983,13 +981,6 @@
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
- // Force initialization of the random number generator
- if (log.isDebugEnabled())
- log.debug("Force random number initialization starting");
- String dummy = generateSessionId();
- if (log.isDebugEnabled())
- log.debug("Force random number initialization completed");
-
if (store == null)
log.error("No Store configured, persistence disabled");
else if (store instanceof Lifecycle)
@@ -1036,9 +1027,6 @@
if (getStore() != null && getStore() instanceof Lifecycle)
((Lifecycle)getStore()).stop();
- // Require a new random number generator if we are restarted
- this.random = null;
-
if( initialized )
destroy();
Modified: trunk/java/org/apache/catalina/session/StandardManager.java
===================================================================
--- trunk/java/org/apache/catalina/session/StandardManager.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/catalina/session/StandardManager.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -34,6 +34,7 @@
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.Random;
import javax.servlet.ServletContext;
@@ -279,7 +280,7 @@
* @exception IllegalStateException if a new session cannot be
* instantiated for any reason
*/
- public Session createSession(String sessionId) {
+ public Session createSession(String sessionId, Random random) {
if ((maxActiveSessions >= 0) &&
(sessions.size() >= maxActiveSessions)) {
@@ -288,7 +289,7 @@
(sm.getString("standardManager.createSession.ise"));
}
- return (super.createSession(sessionId));
+ return (super.createSession(sessionId, random));
}
@@ -627,13 +628,6 @@
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
- // Force initialization of the random number generator
- if (log.isDebugEnabled())
- log.debug("Force random number initialization starting");
- String dummy = generateSessionId();
- if (log.isDebugEnabled())
- log.debug("Force random number initialization completed");
-
// Load unloaded sessions, if any
try {
load();
@@ -685,9 +679,6 @@
}
}
- // Require a new random number generator if we are restarted
- this.random = null;
-
if( initialized ) {
destroy();
}
Modified: trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
===================================================================
--- trunk/java/org/apache/tomcat/util/net/AprEndpoint.java 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/java/org/apache/tomcat/util/net/AprEndpoint.java 2010-11-19 16:06:19 UTC (rev 1579)
@@ -186,7 +186,7 @@
/**
* Size of the socket poller.
*/
- protected int pollerSize = (OS.IS_WIN32 || OS.IS_WIN64) ? (8 * 1024) : (32 * 1024);
+ protected int pollerSize = -1;
public void setPollerSize(int pollerSize) { this.pollerSize = pollerSize; }
public int getPollerSize() { return pollerSize; }
@@ -194,7 +194,7 @@
/**
* Size of the sendfile (= concurrent files which can be served).
*/
- protected int sendfileSize = (OS.IS_WIN32 || OS.IS_WIN64) ? (1 * 1024) : (16 * 1024);
+ protected int sendfileSize = -1;
public void setSendfileSize(int sendfileSize) { this.sendfileSize = sendfileSize; }
public int getSendfileSize() { return sendfileSize; }
@@ -582,6 +582,14 @@
useSendfile = false;
}
+ // Poller size defaults
+ if (pollerSize <= 0) {
+ pollerSize = (OS.IS_WIN32 || OS.IS_WIN64) ? (8 * 1024) : (32 * 1024);
+ }
+ if (sendfileSize <= 0) {
+ sendfileSize = (OS.IS_WIN32 || OS.IS_WIN64) ? (1 * 1024) : (16 * 1024);
+ }
+
long inetAddress = Address.info(addressStr, family,
port, 0, rootPool);
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2010-11-10 05:25:41 UTC (rev 1578)
+++ trunk/webapps/docs/changelog.xml 2010-11-19 16:06:19 UTC (rev 1579)
@@ -25,6 +25,9 @@
<fix>
<jira>189</jira>: Overlay timestamps need special treatment. (remm)
</fix>
+ <fix>
+ Improve session id creation. (remm)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
14 years, 10 months
JBossWeb SVN: r1578 - branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398/src/share/classes/org/apache/tomcat/util/http.
by jbossweb-commits@lists.jboss.org
Author: mmillson
Date: 2010-11-10 00:25:41 -0500 (Wed, 10 Nov 2010)
New Revision: 1578
Modified:
branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398/src/share/classes/org/apache/tomcat/util/http/Cookies.java
Log:
Fix for version 0 cookies support for [JBPAPP-5398].
Modified: branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398/src/share/classes/org/apache/tomcat/util/http/Cookies.java
===================================================================
--- branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398/src/share/classes/org/apache/tomcat/util/http/Cookies.java 2010-11-10 03:52:37 UTC (rev 1577)
+++ branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398/src/share/classes/org/apache/tomcat/util/http/Cookies.java 2010-11-10 05:25:41 UTC (rev 1578)
@@ -60,14 +60,21 @@
'\t':9 ' ':32 '\"':34 '\'':39 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60
'=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
*/
- public static final char SEPARATORS[] = { '\t', ' ', '\"', '\'', '(', ')', ',',
- ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
+ public static final char SEPARATORS[];
protected static final boolean separators[] = new boolean[128];
static {
for (int i = 0; i < 128; i++) {
separators[i] = false;
}
+ if (Boolean.valueOf(System.getProperty("org.apache.tomcat.util.http.ServerCookie.VERSION_SWITCH", "false")).booleanValue()) {
+ /* Version 1 separators */
+ SEPARATORS = new char[] { '\t', ' ', '\"', '\'', '(', ')', ',',
+ ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
+ } else {
+ /* Version 0 separators */
+ SEPARATORS = new char[] { ',', ';', ' ', '\t', '='};
+ }
for (int i = 0; i < SEPARATORS.length; i++) {
separators[SEPARATORS[i]] = true;
}
14 years, 10 months
JBossWeb SVN: r1577 - branches.
by jbossweb-commits@lists.jboss.org
Author: mmillson
Date: 2010-11-09 22:52:37 -0500 (Tue, 09 Nov 2010)
New Revision: 1577
Added:
branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398/
Log:
Create JBPAPP-5398 patch branch from JBOSSWEB_2_0_0_GA_CP14 tag
Copied: branches/JBOSSWEB_2_0_0_GA_CP14_JBPAPP-5398 (from rev 1576, tags/JBOSSWEB_2_0_0_GA_CP14)
14 years, 10 months
JBossWeb SVN: r1576 - in branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes: org/apache/el/lang and 1 other directories.
by jbossweb-commits@lists.jboss.org
Author: mmillson
Date: 2010-11-09 17:42:33 -0500 (Tue, 09 Nov 2010)
New Revision: 1576
Modified:
branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/javax/el/BeanELResolver.java
branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/lang/ExpressionBuilder.java
branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/util/ConcurrentCache.java
Log:
Fix Concurrent access to WeakHashMap in ConcurrentCache causing infinite loop and 100% CPU for [JBPAPP-5344].
Modified: branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/javax/el/BeanELResolver.java
===================================================================
--- branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/javax/el/BeanELResolver.java 2010-11-09 21:09:02 UTC (rev 1575)
+++ branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/javax/el/BeanELResolver.java 2010-11-09 22:42:33 UTC (rev 1576)
@@ -25,6 +25,8 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@@ -34,11 +36,30 @@
public class BeanELResolver extends ELResolver {
- private final boolean readOnly;
+ private static final int CACHE_SIZE;
+ private static final String CACHE_SIZE_PROP =
+ "org.apache.el.BeanELResolver.CACHE_SIZE";
- private final ConcurrentCache<String, BeanProperties> cache = new ConcurrentCache<String, BeanProperties>(
- 1000);
+ static {
+ if (System.getSecurityManager() == null) {
+ CACHE_SIZE = Integer.parseInt(
+ System.getProperty(CACHE_SIZE_PROP, "1000"));
+ } else {
+ CACHE_SIZE = AccessController.doPrivileged(
+ new PrivilegedAction<Integer>() {
+ public Integer run() {
+ return Integer.valueOf(
+ System.getProperty(CACHE_SIZE_PROP, "1000"));
+ }
+ }).intValue();
+ }
+ }
+ private final boolean readOnly;
+
+ private final ConcurrentCache<String, BeanProperties> cache =
+ new ConcurrentCache<String, BeanProperties>(CACHE_SIZE);
+
public BeanELResolver() {
this.readOnly = false;
}
@@ -299,34 +320,37 @@
private final static class ConcurrentCache<K,V> {
- private final int size;
- private final Map<K,V> eden;
- private final Map<K,V> longterm;
-
- public ConcurrentCache(int size) {
- this.size = size;
- this.eden = new ConcurrentHashMap<K,V>(size);
- this.longterm = new WeakHashMap<K,V>(size);
- }
-
- public V get(K key) {
- V value = this.eden.get(key);
- if (value == null) {
- value = this.longterm.get(key);
- if (value != null) {
- this.eden.put(key, value);
- }
- }
- return value;
- }
-
- public void put(K key, V value) {
- if (this.eden.size() >= this.size) {
- this.longterm.putAll(this.eden);
- this.eden.clear();
- }
- this.eden.put(key, value);
- }
-
+ private final int size;
+ private final Map<K,V> eden;
+ private final Map<K,V> longterm;
+
+ public ConcurrentCache(int size) {
+ this.size = size;
+ this.eden = new ConcurrentHashMap<K,V>(size);
+ this.longterm = new WeakHashMap<K,V>(size);
+ }
+
+ public V get(K key) {
+ V value = this.eden.get(key);
+ if (value == null) {
+ synchronized (longterm) {
+ value = this.longterm.get(key);
+ }
+ if (value != null) {
+ this.eden.put(key, value);
+ }
+ }
+ return value;
+ }
+
+ public void put(K key, V value) {
+ if (this.eden.size() >= this.size) {
+ synchronized (longterm) {
+ this.longterm.putAll(this.eden);
+ }
+ this.eden.clear();
+ }
+ this.eden.put(key, value);
+ }
}
}
Modified: branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/lang/ExpressionBuilder.java
===================================================================
--- branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/lang/ExpressionBuilder.java 2010-11-09 21:09:02 UTC (rev 1575)
+++ branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/lang/ExpressionBuilder.java 2010-11-09 22:42:33 UTC (rev 1576)
@@ -19,6 +19,8 @@
import java.io.StringReader;
import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.el.ELContext;
import javax.el.ELException;
@@ -50,8 +52,28 @@
*/
public final class ExpressionBuilder implements NodeVisitor {
- private static final ConcurrentCache cache = new ConcurrentCache(5000);
+ private static final int CACHE_SIZE;
+ private static final String CACHE_SIZE_PROP =
+ "org.apache.el.ExpressionBuilder.CACHE_SIZE";
+ static {
+ if (System.getSecurityManager() == null) {
+ CACHE_SIZE = Integer.parseInt(
+ System.getProperty(CACHE_SIZE_PROP, "5000"));
+ } else {
+ CACHE_SIZE = AccessController.doPrivileged(
+ new PrivilegedAction<Integer>() {
+ public Integer run() {
+ return Integer.valueOf(
+ System.getProperty(CACHE_SIZE_PROP, "5000"));
+ }
+ }).intValue();
+ }
+ }
+
+ private static final ConcurrentCache<String, Node> cache =
+ new ConcurrentCache<String, Node>(CACHE_SIZE);
+
private FunctionMapper fnMapper;
private VariableMapper varMapper;
Modified: branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/util/ConcurrentCache.java
===================================================================
--- branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/util/ConcurrentCache.java 2010-11-09 21:09:02 UTC (rev 1575)
+++ branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/src/share/classes/org/apache/el/util/ConcurrentCache.java 2010-11-09 22:42:33 UTC (rev 1576)
@@ -21,7 +21,9 @@
public V get(K k) {
V v = this.eden.get(k);
if (v == null) {
- v = this.longterm.get(k);
+ synchronized (longterm) {
+ v = this.longterm.get(k);
+ }
if (v != null) {
this.eden.put(k, v);
}
@@ -31,7 +33,9 @@
public void put(K k, V v) {
if (this.eden.size() >= size) {
- this.longterm.putAll(this.eden);
+ synchronized (longterm) {
+ this.longterm.putAll(this.eden);
+ }
this.eden.clear();
}
this.eden.put(k, v);
14 years, 10 months
JBossWeb SVN: r1575 - branches.
by jbossweb-commits@lists.jboss.org
Author: mmillson
Date: 2010-11-09 16:09:02 -0500 (Tue, 09 Nov 2010)
New Revision: 1575
Added:
branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344/
Log:
Create JBPAPP-5344 patch branch from JBOSSWEB_2_0_0_GA_CP11 tag
Copied: branches/JBOSSWEB_2_0_0_GA_CP11_JBPAPP-5344 (from rev 1574, tags/JBOSSWEB_2_0_0_GA_CP11)
14 years, 10 months