Now that tools are being implemented to access the cache manager via http:// scheme we need to accomodate the browser XSS protection mechanisms which limit XHR based scripts abilities.

This adds CORS headers to manager responses. Permitting XHR to view the Server header (to detect squid version for known capabilities) and to flag that the XHR request may need access to credentials for authenticating with the manager.

This also closes the feature bug 3407 requesting we support the non-standard "Origin:" header, which is used by the CORS mechanisms.

Future work:
Support the OPTIONS request used by CORS to detect requirements before POSTing. We do not yet use POST in the main code so that is left until needed.

Amos

=== modified file 'src/HttpHeader.cc'
--- src/HttpHeader.cc   2011-12-12 16:46:49 +0000
+++ src/HttpHeader.cc   2011-12-23 09:15:25 +0000
@@ -116,6 +116,7 @@
     {"Max-Forwards", HDR_MAX_FORWARDS, ftInt64},
     {"Mime-Version", HDR_MIME_VERSION, ftStr}, /* for now */
     {"Negotiate", HDR_NEGOTIATE, ftStr},
+    {"Origin", HDR_ORIGIN, ftStr},
     {"Pragma", HDR_PRAGMA, ftStr},
     {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr},
     {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr},
@@ -231,6 +232,7 @@
     HDR_ACCEPT_RANGES, HDR_AGE,
     HDR_LOCATION, HDR_MAX_FORWARDS,
     HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE, 
HDR_SET_COOKIE2,
+    HDR_ORIGIN,
     HDR_VARY,
     HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE,
     HDR_X_CACHE_LOOKUP,
@@ -249,7 +251,9 @@
 static http_hdr_type RequestHeadersArr[] = {
     HDR_AUTHORIZATION, HDR_FROM, HDR_HOST,
     HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH,
-    HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION,
+    HDR_IF_RANGE, HDR_MAX_FORWARDS,
+    HDR_ORIGIN,
+    HDR_PROXY_CONNECTION,
     HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE,
     HDR_USER_AGENT, HDR_X_FORWARDED_FOR, HDR_SURROGATE_CAPABILITY
 };

=== modified file 'src/HttpHeader.h'
--- src/HttpHeader.h    2011-12-02 11:20:58 +0000
+++ src/HttpHeader.h    2011-12-23 09:17:32 +0000
@@ -101,6 +101,7 @@
     HDR_MIME_VERSION,                   /**< RFC 2626 */
     HDR_NEGOTIATE,                      /**< experimental RFC 2295. Why only 
this one from 2295? */
     /*HDR_OVERWRITE,*/                  /* RFC 2518 */
+    HDR_ORIGIN,                         /* CORS Draft specification (see 
http://www.w3.org/TR/cors/) */
     HDR_PRAGMA,                         /**< deprecated RFC 2068,2616 header 
we may need to erase */
     HDR_PROXY_AUTHENTICATE,             /**< RFC 2608, 2616, 2617 */
     HDR_PROXY_AUTHENTICATION_INFO,      /**< RFC 2617 */

=== modified file 'src/cache_manager.cc'
--- src/cache_manager.cc        2011-11-27 12:37:35 +0000
+++ src/cache_manager.cc        2011-12-23 10:14:00 +0000
@@ -371,6 +371,14 @@
          */
         rep->header.putAuth("Basic", actionName);
 #endif
+        // Allow cachemgr and other XHR scripts access to our version string
+        if (request->header.has(HDR_ORIGIN)) {
+            
rep->header.putExt("Access-Control-Allow-Origin",request->header.getStr(HDR_ORIGIN));
+#if HAVE_AUTH_MODULE_BASIC
+            rep->header.putExt("Access-Control-Allow-Credentials","true");
+#endif
+            rep->header.putExt("Access-Control-Expose-Headers","Server");
+        }
 
         /* store the reply */
         entry->replaceHttpReply(rep);
@@ -382,6 +390,10 @@
         return;
     }
 
+    if (request->header.has(HDR_ORIGIN)) {
+        cmd->params.httpOrigin = request->header.getStr(HDR_ORIGIN);
+    }
+
     debugs(16, 2, "CacheManager: " <<
            userName << "@" <<
            client << " requesting '" <<

=== modified file 'src/mgr/Action.cc'
--- src/mgr/Action.cc   2011-10-03 20:27:34 +0000
+++ src/mgr/Action.cc   2011-12-23 10:09:47 +0000
@@ -102,6 +102,15 @@
     if (writeHttpHeader) {
         HttpReply *rep = new HttpReply;
         rep->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, 
squid_curtime);
+        // Allow cachemgr and other XHR scripts access to our version string
+        const ActionParams &params = command().params;
+        if (params.httpOrigin.size() > 0) {
+            rep->header.putExt("Access-Control-Allow-Origin", 
params.httpOrigin.termedBuf());
+#if HAVE_AUTH_MODULE_BASIC
+            rep->header.putExt("Access-Control-Allow-Credentials","true");
+#endif
+            rep->header.putExt("Access-Control-Expose-Headers","Server");
+        }
         entry->replaceHttpReply(rep);
     }
 

=== modified file 'src/mgr/ActionParams.cc'
--- src/mgr/ActionParams.cc     2011-01-24 17:24:59 +0000
+++ src/mgr/ActionParams.cc     2011-12-23 09:50:46 +0000
@@ -23,6 +23,7 @@
     httpMethod = static_cast<_method_t>(m);
 
     msg.getPod(httpFlags);
+    msg.getString(httpOrigin);
 
     msg.getString(actionName);
     msg.getString(userName);
@@ -36,6 +37,7 @@
     msg.putString(httpUri);
     msg.putInt(httpMethod);
     msg.putPod(httpFlags);
+    msg.putString(httpOrigin);
 
     msg.putString(actionName);
     msg.putString(userName);

=== modified file 'src/mgr/ActionParams.h'
--- src/mgr/ActionParams.h      2011-01-24 17:24:59 +0000
+++ src/mgr/ActionParams.h      2011-12-23 09:50:01 +0000
@@ -29,6 +29,7 @@
     String httpUri; ///< HTTP request URI
     _method_t httpMethod; ///< HTTP request method
     request_flags httpFlags; ///< HTTP request flags
+    String httpOrigin;       ///< HTTP Origin: header (if any)
 
     /* action parameters extracted from the client HTTP request */
     String actionName; ///< action name (and credentials realm)

Reply via email to