* Set session cookie in request object. Fixes bug 547.

http://helma.org/bugs/show_bug.cgi?id=547
* Use java.security.SecureRandom for session id generation,
  with fallback to java.util.Random.
This commit is contained in:
hns 2007-09-25 11:01:30 +00:00
parent f7f2604969
commit fd598f23cf

View file

@ -24,6 +24,8 @@ import helma.framework.core.Application;
import helma.util.*; import helma.util.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.*; import javax.servlet.http.*;
@ -64,6 +66,11 @@ public abstract class AbstractServletClient extends HttpServlet {
// if fals, an error response is written to the client immediately without entering helma // if fals, an error response is written to the client immediately without entering helma
boolean uploadSoftfail = false; boolean uploadSoftfail = false;
// Random number generator for session ids
Random random;
// whether the random number generator is secure
boolean secureRandom;
/** /**
* Init this servlet. * Init this servlet.
* *
@ -113,6 +120,20 @@ public abstract class AbstractServletClient extends HttpServlet {
// generally disable response caching for clients? // generally disable response caching for clients?
caching = !("false".equalsIgnoreCase(init.getInitParameter("caching"))); caching = !("false".equalsIgnoreCase(init.getInitParameter("caching")));
// Get random number generator for session ids
try {
random = SecureRandom.getInstance("SHA1PRNG");
secureRandom = true;
} catch (NoSuchAlgorithmException nsa) {
random = new Random();
secureRandom = false;
}
random.setSeed(random.nextLong() ^ System.currentTimeMillis()
^ hashCode()
^ Runtime.getRuntime().freeMemory());
random.nextLong();
} }
/** /**
@ -157,9 +178,8 @@ public abstract class AbstractServletClient extends HttpServlet {
if (sessionCookieName.equals(key)) { if (sessionCookieName.equals(key)) {
reqtrans.setSession(reqCookies[i].getValue()); reqtrans.setSession(reqCookies[i].getValue());
} else {
reqtrans.setCookie(key, reqCookies[i]);
} }
reqtrans.setCookie(key, reqCookies[i]);
} catch (Exception badCookie) { } catch (Exception badCookie) {
log("Error setting cookie", badCookie); log("Error setting cookie", badCookie);
} }
@ -254,7 +274,8 @@ public abstract class AbstractServletClient extends HttpServlet {
Cookie c = resCookies[i].getCookie("/", resCookieDomain); Cookie c = resCookies[i].getCookie("/", resCookieDomain);
response.addCookie(c); response.addCookie(c);
} catch (Exception ignore) { } catch (Exception x) {
getApplication().logEvent("Error adding cookie: " + x);
} }
} }
@ -351,7 +372,9 @@ public abstract class AbstractServletClient extends HttpServlet {
writer.write("Error in application "); writer.write("Error in application ");
try { try {
writer.write(getApplication().getName()); writer.write(getApplication().getName());
} catch (Exception besafe) {} } catch (Exception besafe) {
// ignore
}
writer.write("</h3>"); writer.write("</h3>");
writer.write(message); writer.write(message);
writer.write("</body></html>"); writer.write("</body></html>");
@ -508,40 +531,46 @@ public abstract class AbstractServletClient extends HttpServlet {
if (protectedSessionCookie) { if (protectedSessionCookie) {
// If protected session cookies are enabled we also force a new session // If protected session cookies are enabled we also force a new session
// if the existing session id doesn't match the client's ip address // if the existing session id doesn't match the client's ip address
StringBuffer b = new StringBuffer(); StringBuffer buffer = new StringBuffer();
addIPAddress(b, request.getRemoteAddr()); addIPAddress(buffer, request.getRemoteAddr());
addIPAddress(b, request.getHeader("X-Forwarded-For")); addIPAddress(buffer, request.getHeader("X-Forwarded-For"));
addIPAddress(b, request.getHeader("Client-ip")); addIPAddress(buffer, request.getHeader("Client-ip"));
if (reqtrans.getSession() == null || !reqtrans.getSession().startsWith(b.toString())) { if (reqtrans.getSession() == null || !reqtrans.getSession().startsWith(buffer.toString())) {
response.addCookie(createSessionCookie(b, reqtrans, domain)); response.addCookie(createSession(buffer.toString(), reqtrans, domain));
} }
} else if (reqtrans.getSession() == null) { } else if (reqtrans.getSession() == null) {
response.addCookie(createSessionCookie(new StringBuffer(), reqtrans, domain)); response.addCookie(createSession("", reqtrans, domain));
} }
} }
/** /**
* Create a new session cookie. * Create a new session cookie.
* *
* @param b * @param prefix the session id prefix
* @param reqtrans * @param reqtrans the request object
* @param domain * @param domain the cookie domain
* @return the session cookie * @return the session cookie
*/ */
private Cookie createSessionCookie(StringBuffer b, private Cookie createSession(String prefix,
RequestTrans reqtrans, RequestTrans reqtrans,
String domain) { String domain) {
b.append (Long.toString(Math.round(Math.random() * Long.MAX_VALUE) - Application app = getApplication();
System.currentTimeMillis(), 36)); String id = null;
while (id == null || app.getSession(id) != null) {
reqtrans.setSession(b.toString()); long l = secureRandom ?
Cookie cookie = new Cookie(sessionCookieName, reqtrans.getSession()); random.nextLong() :
random.nextLong() + Runtime.getRuntime().freeMemory() ^ hashCode();
cookie.setPath("/"); if (l < 0)
l = -l;
if (domain != null) { id = prefix + Long.toString(l, 36);
cookie.setDomain(domain);
} }
reqtrans.setSession(id);
Cookie cookie = new Cookie(sessionCookieName, id);
cookie.setPath("/");
if (domain != null)
cookie.setDomain(domain);
return cookie; return cookie;
} }