summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cdn.basic.farfuture.inc39
-rw-r--r--cdn.module36
2 files changed, 64 insertions, 11 deletions
diff --git a/cdn.basic.farfuture.inc b/cdn.basic.farfuture.inc
index 201f746..c88437b 100644
--- a/cdn.basic.farfuture.inc
+++ b/cdn.basic.farfuture.inc
@@ -10,18 +10,18 @@
//----------------------------------------------------------------------------
// Menu system callbacks.
-function cdn_basic_farfuture_download() {
- $args = func_get_args();
-
- // The first argument is the file's mtime. We don't need this anymore.
- $ufi = array_shift($args);
-
- // Reconstruct the path of the requested file.
- $path = implode('/', $args);
+function cdn_basic_farfuture_download($token, $ufi, $path) {
+ // Validate the token to make sure this request originated from CDN.
+ $path_info = pathinfo($path);
+ $sec_token = _cdn_hmac_base64($ufi . $path_info['filename'], drupal_get_private_key() . _cdn_get_hash_salt());
+ if ($token != $sec_token) {
+ header('HTTP/1.1 403 Forbidden');
+ exit();
+ }
// Disallow downloading of files that are also not allowed to be downloaded
// by Drupal's .htaccess file.
- if (preg_match("/\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$/", $path)) {
+ if (preg_match("/\.(engine|inc|info|install|make|module|profile|test|po|sh|php([3-6])?|phtml|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$/", $path)) {
drupal_access_denied();
exit();
}
@@ -421,3 +421,24 @@ function _cdn_basic_farfuture_create_directory_structure($path) {
file_check_directory(file_create_path($directory), FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
}
}
+
+/**
+ * Gets a salt useful for hardening.
+ *
+ * Based on Drupal 7's drupal_get_hash_salt().
+ */
+function _cdn_get_hash_salt() {
+ global $db_url;
+ return hash('sha256', serialize($db_url));
+}
+
+/**
+ * Calculates a base-64 encoded, URL-safe sha-256 hmac.
+ *
+ * Based on Drupal 7's drupal_hmac_base64().
+ */
+function _cdn_hmac_base64($data, $key) {
+ $hmac = base64_encode(hash_hmac('sha256', $data, $key, TRUE));
+ // Modify the hmac so it's safe to use in URLs.
+ return strtr($hmac, array('+' => '-', '/' => '_', '=' => ''));
+}
diff --git a/cdn.module b/cdn.module
index 6a3c3c1..2b72580 100644
--- a/cdn.module
+++ b/cdn.module
@@ -149,7 +149,13 @@ function cdn_file_url_alter(&$path) {
$path = drupal_urlencode($path);
// Generate the new path.
$path_before_farfuture = $path;
- $path = "cdn/farfuture/$ufi/$path";
+
+ // Generate a unique token to verify that the request was generated by
+ // CDN. We cannot use drupal_get_token() since it depends on the user
+ // session.
+ $path_info = pathinfo(urldecode($path));
+ $token = _cdn_hmac_base64($ufi . $path_info['filename'], drupal_get_private_key() . _cdn_get_hash_salt());
+ $path = "cdn/farfuture/$token/$ufi/$path";
}
// Load the include file that contains the logic for the mode that's
@@ -336,11 +342,13 @@ function cdn_menu() {
);
// Origin Pull mode's Far Future expiration support.
- $items['cdn/farfuture'] = array(
+ $items['cdn/farfuture/%/%/%cdn_basic_farfuture_tail'] = array(
'title' => 'Download a far futured file',
'access callback' => TRUE,
'page callback' => 'cdn_basic_farfuture_download',
+ 'page arguments' => array(2, 3, 4),
'type' => MENU_CALLBACK,
+ 'load arguments' => array('%map', '%index'),
'file' => 'cdn.basic.farfuture.inc',
);
@@ -504,6 +512,30 @@ function cdn_cdn_blacklist() {
//----------------------------------------------------------------------------
+// Menu system callbacks.
+
+/**
+ * Implements %wildcard_to_arg().
+ *
+ * Identical to menu_tail_to_arg() in Drupal 6 and 7.
+ */
+function cdn_basic_farfuture_tail_to_arg($arg, $map, $index) {
+ return implode('/', array_slice($map, $index));
+}
+
+/**
+ * Implements %wildcard_load().
+ *
+ * Backport of menu_tail_load() of Drupal 7; does not exist in Drupal 6.
+ */
+function cdn_basic_farfuture_tail_load($arg, $map, $index) {
+ $arg = implode('/', array_slice($map, $index));
+ $map = array_slice($map, 0, $index);
+ return $arg;
+}
+
+
+//----------------------------------------------------------------------------
// Public functions.
/**