diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php
index fb3a0687e997bf577c5454ba34b8a6d7a3e6999a..daa04a110a621ecb5851b15119a497531d092ed0 100644
--- a/modules/simpletest/drupal_web_test_case.php
+++ b/modules/simpletest/drupal_web_test_case.php
@@ -591,6 +591,16 @@ class DrupalWebTestCase extends DrupalTestCase {
    */
   protected $httpauth_credentials = NULL;
 
+  /**
+   * The current session name, if available.
+   */
+  protected $session_name = NULL;
+
+  /**
+   * The current session ID, if available.
+   */
+  protected $session_id = NULL;
+
   /**
    * Constructor for DrupalWebTestCase.
    */
@@ -913,6 +923,14 @@ protected function drupalLogin(stdClass $user) {
     }
   }
 
+  /**
+   * Generate a token for the currently logged in user.
+   */
+  protected function drupalGetToken($value = '') {
+    $private_key = drupal_get_private_key();
+    return md5($this->session_id . $value . $private_key);
+  }
+
   /*
    * Logs a user out of the internal browser, then check the login page to confirm logout.
    */
@@ -1121,6 +1139,9 @@ protected function curlInitialize() {
         $curl_options[CURLOPT_USERPWD] = $this->httpauth_credentials;
       }
       curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
+
+      // By default, the child session name should be the same as the parent.
+      $this->session_name = session_name();
     }
   }
 
@@ -1144,7 +1165,11 @@ protected function curlExec($curl_options) {
       $curl_options[CURLOPT_HTTPHEADER][] = 'Expect:';
     }
     curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
+
+    // Reset headers and the session ID.
+    $this->session_id = NULL;
     $this->headers = array();
+
     $this->drupalSetContent(curl_exec($this->curlHandle), curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL));
     $message_vars = array(
       '!method' => !empty($curl_options[CURLOPT_NOBODY]) ? 'HEAD' : (empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST'),
@@ -1169,6 +1194,7 @@ protected function curlExec($curl_options) {
    */
   protected function curlHeaderCallback($curlHandler, $header) {
     $this->headers[] = $header;
+
     // Errors are being sent via X-Drupal-Assertion-* headers,
     // generated by _drupal_log_error() in the exact form required
     // by DrupalWebTestCase::error().
@@ -1176,6 +1202,17 @@ protected function curlHeaderCallback($curlHandler, $header) {
       // Call DrupalWebTestCase::error() with the parameters from the header.
       call_user_func_array(array(&$this, 'error'), unserialize(urldecode($matches[1])));
     }
+
+    // Save the session cookie, if set.
+    if (preg_match('/^Set-Cookie: ' . preg_quote($this->session_name) . '=([a-z90-9]+)/', $header, $matches)) {
+      if ($matches[1] != 'deleted') {
+        $this->session_id = $matches[1];
+      }
+      else {
+        $this->session_id = NULL;
+      }
+    }
+
     // This is required by cURL.
     return strlen($header);
   }