You are here

ServicesSecurityTests.test in Services 7.3

File

tests/functional/ServicesSecurityTests.test
View source
<?php

class ServicesSecurityTests extends ServicesWebTestCase {

  // Class variables
  protected $privileged_user = NULL;

  // Endpoint details.
  protected $endpoint = NULL;

  /**
   * {@inheritdoc}
   */
  public function setUp(array $modules = array()) {
    parent::setUp($modules);

    // Set up endpoint.
    $this->endpoint = $this
      ->saveNewEndpoint();

    // Create and log in our privileged user.
    $this->privileged_user = $this
      ->drupalCreateUser(array(
      'get a system variable',
      'set a system variable',
    ));
    $this
      ->drupalLogin($this->privileged_user);
  }

  /**
   * Implementation of getInfo().
   */
  public static function getInfo() {
    return array(
      'name' => t('Security'),
      'description' => t('Security tests.'),
      'group' => t('Services'),
      // The libraries module is required by rest_service, which is used by
      // ServicesEndpointTests.
      'dependencies' => array(
        'ctools',
        'libraries',
      ),
    );
  }
  public function testSessionCSRF() {
    $variable_name = $this
      ->randomName();
    $variable_value = $this
      ->randomString();
    $default_variable_value = $this
      ->randomString();
    $this
      ->servicesPost($this->endpoint->path . '/system/set_variable', array(
      'name' => $variable_name,
      'value' => $variable_value,
    ));
    $get_variable_args = array(
      'name' => $variable_name,
      'default' => $default_variable_value,
    );
    $response = $this
      ->servicesPostNoCSRFHeader($this->endpoint->path . '/system/get_variable', $get_variable_args);
    $this
      ->assertEqual($response['status'], 'HTTP/1.1 401 Unauthorized : CSRF validation failed');
    $bad_csrf_token_headers = array(
      'X-CSRF-Token: ' . $this
        ->randomString(),
    );
    $response = $this
      ->servicesPostNoCSRFHeader($this->endpoint->path . '/system/get_variable', $get_variable_args, $bad_csrf_token_headers);
    $this
      ->assertEqual($response['status'], 'HTTP/1.1 401 Unauthorized : CSRF validation failed');
    $csrf_token = $this
      ->drupalGet('services/session/token');
    $good_csrf_token_headers = array(
      'X-CSRF-Token: ' . $csrf_token,
    );
    $response = $this
      ->servicesPostNoCSRFHeader($this->endpoint->path . '/system/get_variable', $get_variable_args, $good_csrf_token_headers);
    $this
      ->assertEqual($response['body'], $variable_value, 'Value of variable retrieved.');
  }

  /**
   * Copy of servicesPost method but without CSRF header.
   */
  protected function servicesPostNoCSRFHeader($url, $data = array(), $headers = array(), $call_type = 'php') {
    switch ($call_type) {
      case 'php':

        // Add .php to get serialized response.
        $url = $this
          ->getAbsoluteUrl($url) . '.php';

        // Otherwise Services will reject arguments.
        $headers[] = "Content-type: application/x-www-form-urlencoded";

        // Prepare arguments.
        $post = drupal_http_build_query($data, '', '&');
        break;
      case 'json':

        // Add .json to get json encoded response.
        $url = $this
          ->getAbsoluteUrl($url) . '.json';

        // Set proper headers.
        $headers[] = "Content-type: application/json";

        // Prepare arguments.
        $post = json_encode($data);
        break;
    }
    $content = $this
      ->curlExec(array(
      CURLOPT_URL => $url,
      CURLOPT_POST => TRUE,
      CURLOPT_POSTFIELDS => $post,
      CURLOPT_HTTPHEADER => $headers,
      CURLOPT_HEADER => TRUE,
      CURLOPT_RETURNTRANSFER => TRUE,
    ));

    // Parse response.
    list($info, $header, $status, $code, $body) = $this
      ->parseHeader($content, $call_type);
    $this
      ->verbose('POST request to: ' . $url . '<hr />Arguments: ' . highlight_string('<?php ' . var_export($data, TRUE), TRUE) . '<hr />Raw POST body: ' . $post . '<hr />Response: ' . highlight_string('<?php ' . var_export($body, TRUE), TRUE) . '<hr />Curl info: ' . highlight_string('<?php ' . var_export($info, TRUE), TRUE) . '<hr />Raw response: ' . $content);
    return array(
      'header' => $header,
      'status' => $status,
      'code' => $code,
      'body' => $body,
    );
  }

}

Classes