diff -urp includes/menu.inc includes/menu.inc
--- includes/menu.inc	2008-11-04 12:56:36.000000000 +0200
+++ includes/menu.inc	2008-11-04 12:55:04.000000000 +0200
@@ -476,7 +476,7 @@ function _menu_load_objects(&$item, &$ma
 }
 
 /**
- * Check access to a menu item using the access callback
+ * Check access to a menu item using the access callback.
  *
  * @param $item
  *   A menu router or menu link item
@@ -486,24 +486,42 @@ function _menu_load_objects(&$item, &$ma
  *   $item['access'] becomes TRUE if the item is accessible, FALSE otherwise.
  */
 function _menu_check_access(&$item, $map) {
+  // Turn callback into an array so modules may add their own access check.
+  $item['access_callbacks'] = array(
+    array(
+      'access_callback' => empty($item['access_callback']) ? 0 : trim($item['access_callback']),
+      'access_arguments' => menu_unserialize($item['access_arguments'], $map),
+    ),
+  );
+  // Allow other modules to add their own permissions.
+  drupal_alter('menu_check_access', $item);
+
   // Determine access callback, which will decide whether or not the current
   // user has access to this path.
-  $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
-  // Check for a TRUE or FALSE value.
-  if (is_numeric($callback)) {
-    $item['access'] = (bool)$callback;
-  }
-  else {
-    $arguments = menu_unserialize($item['access_arguments'], $map);
-    // As call_user_func_array is quite slow and user_access is a very common
-    // callback, it is worth making a special case for it.
-    if ($callback == 'user_access') {
-      $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
+  $return = TRUE;
+  foreach ($item['access_callbacks'] as $key => $value) {
+    $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
+    // Check for a TRUE or FALSE value.
+    if (is_numeric($callback)) {
+      if (!$return = (bool)$callback) {
+        break;
+      }
     }
     else {
-      $item['access'] = call_user_func_array($callback, $arguments);
+      $arguments = $value['access_arguments'];
+      // As call_user_func_array is quite slow and user_access is a very common
+      // callback, it is worth making a special case for it.
+      if ($callback == 'user_access') {
+        if (!$return = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1])) {
+          break;
+        }
+      }
+      elseif (!$return = call_user_func_array($callback, $arguments)) {
+          break;
+      }
     }
   }
+  $item['access'] = $return;
 }
 
 /**
