referer verification
Is there a way to setup a check to verify a user is accessing a directory after coming from a verification servlet on the server?
I was planning on using a referer check in the obj.conf for the server.
<If $uri ="/somedir/*">
<Client match="none" referer="*CheckServlet*">
NameTrans fn="restart" uri="/LoginServlet?loc=$uri"
</Client>
</If>
But that can be circumvented with a Firefox plug-in to spoof referer information. At the same time I do not see referer being populated when using RequestDispatcher.forward() to forward the valid login.
[730 byte] By [
bartmcpa] at [2007-11-27 10:57:18]

# 1
I don't think you need the nested Client tag:
<If $uri =~ "^/somedir/(.*)"
and $referer !~ "CheckServlet">
NameTrans fn="restart" uri="/LoginServlet?loc=$1"
</if>
If you're worried about people simply faking the referer header, set a tracking cookie, then check for it too:
<If $uri =~ "^/somedir/(.*)"
and $referer !~ "CheckServlet"
and not defined $cookie{'VISITID'}>
ObjectType fn="set-cookie" name="VISITID" value="$(uuid())"
NameTrans fn="restart" uri="/LoginServlet?loc=$1"
</if>
While not 100% perfect, this means someone trying to circumvent your protection has to know the proper Referer header to send, plus the proper Cookie name.
As a side benefit of this method, you could now log this cookie and use it for user tracking as they move around the site:
<access-log>
<file>../logs/access</file>
<format>"%Req->reqpb.clf-request%" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length% "$cookie{'VISITID'}"</format>
</access-log>
Note: I cobbled this together from the docs on pattern matching at:
http://docs.sun.com/app/docs/doc/820-1062/6ncoqnpfh?a=view
and one of Chris Elving's blog entries at:
http://blogs.sun.com/elving/entry/user_tracking_cookie
I haven't actually tried it. Some massaging of the syntax may be needed. Please post back and let us know how it worked out.
# 4
Thanks for the help Joe!
I have switched to the sendRedirect method, but the server is still not seeing the referer getting set.
My Java logic is as follows:
A cookie checking servlet checks to see if the required cookie exists and if the value of the cookie matches the value stored in the user's session. If so, it does the sendRedirect to the requested uri. If not, it forwards the request back to the login jsp.
The login jsp posts to an authentication servlet. The authentication servlet checks the login user/password against the security repository (AD in this case). If the login information is correct it creates the required cookie and session attribute. It sets both to the value of the uuid passed in and then does a sendRedirect to the requested uri.
Here is Java code in the cookie check servlet
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,
IOException {
System.err.println("In CookieCheckServlet");
HttpSession htSess = req.getSession(true);
htSess.setMaxInactiveInterval(3600);
String strLoc = req.getParameter("loc");
String strReqCookie = req.getParameter("ReqInfo");
String SessionUser = (String) htSess.getAttribute("SessionUser");
boolean blCookieFound = false;
Cookie cookieArray[] = req.getCookies();
Cookie currCookie = null;
if (cookieArray != null) {
for (int i = 0; i < cookieArray.length; i++) {
currCookie = cookieArray[i];
if (currCookie.getName().equals(strReqCookie)) {
blCookieFound = true;
break;
}
}
}
if (blCookieFound && SessionUser != null) {
if (currCookie.getValue().equals(SessionUser)) {
// Cookie and Session info match forward to requested resource
System.err.println("Valid Login information");
res.setHeader("referer", "CookieCheckServlet");
res.sendRedirect(strLoc);
} else {
// Cookie does not match session forward to login
System.err.println("Session " + SessionUser + " != cookie " + currCookie.getValue());
req.setAttribute("strMessage", "Invalid session. Please login again.");
RequestDispatcher rd = getServletContext().getRequestDispatcher("/index.jsp");
rd.forward(req, res);
}
} else {
// No cookie or session information forward to login
System.err.println("cookie found = " + blCookieFound + " sessuid null = "
+ (SessionUser == null));
req.setAttribute("strMessage", "No session. Please login.");
RequestDispatcher rd = getServletContext().getRequestDispatcher("/index.jsp");
rd.forward(req, res);
}
}
}
virtual server's obj.conf file (redirects used to make sure the user uses SSL when loggin in)
<If $uri =~ '^/ResourceCheck/(.*)'>
<Client security="false">
NameTrans fn="redirect" url-prefix="https://sub.domain.edu"
</Client>
</If>
<If $uri !~ '^/ResourceCheck/(.*)'>
<Client security="true">
NameTrans fn="redirect" url-prefix="http://sub.domain.edu"
</Client>
</If>
<If $uri = "/mydir/*">
<If not defined $referer or $referer !~ '^/ResourceCheck/(.*)'>
NameTrans fn="restart" uri="/ResourceCheck/CookieCheckServlet?loc=$uri&uid=$(uuid())&ReqInfo=$(lookup('cookiemap.conf','/mydir'))"
</If>
</If>
There is an infinite loop happening with this setup. (Firefox catches it and tells me there is an issue)
In the errors log I see the following logged several times, so the cookie and session info match. The webserver isn't seeing the referer.
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: In CookieCheckServlet
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: Valid Login information
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: In CookieCheckServlet
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: Valid Login information
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: In CookieCheckServlet
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: Valid Login information
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: In CookieCheckServlet
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: Valid Login information
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: In CookieCheckServlet
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: Valid Login information
[19/Jul/2007:10:19:21] warning (18920): CORE3283: stderr: In CookieCheckServlet
[19/Jul/2007:10:19:22] warning (18920): CORE3283: stderr: Valid Login information