|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Provides SimpleTests for core session handling functionality. |
|
6 */ |
|
7 |
|
8 class SessionTestCase extends DrupalWebTestCase { |
|
9 public static function getInfo() { |
|
10 return array( |
|
11 'name' => 'Session tests', |
|
12 'description' => 'Drupal session handling tests.', |
|
13 'group' => 'Session' |
|
14 ); |
|
15 } |
|
16 |
|
17 function setUp() { |
|
18 parent::setUp('session_test'); |
|
19 } |
|
20 |
|
21 /** |
|
22 * Tests for drupal_save_session() and drupal_session_regenerate(). |
|
23 */ |
|
24 function testSessionSaveRegenerate() { |
|
25 $this->assertFalse(drupal_save_session(), 'drupal_save_session() correctly returns FALSE (inside of testing framework) when initially called with no arguments.', 'Session'); |
|
26 $this->assertFalse(drupal_save_session(FALSE), 'drupal_save_session() correctly returns FALSE when called with FALSE.', 'Session'); |
|
27 $this->assertFalse(drupal_save_session(), 'drupal_save_session() correctly returns FALSE when saving has been disabled.', 'Session'); |
|
28 $this->assertTrue(drupal_save_session(TRUE), 'drupal_save_session() correctly returns TRUE when called with TRUE.', 'Session'); |
|
29 $this->assertTrue(drupal_save_session(), 'drupal_save_session() correctly returns TRUE when saving has been enabled.', 'Session'); |
|
30 |
|
31 // Test session hardening code from SA-2008-044. |
|
32 $user = $this->drupalCreateUser(array('access content')); |
|
33 |
|
34 // Enable sessions. |
|
35 $this->sessionReset($user->uid); |
|
36 |
|
37 // Make sure the session cookie is set as HttpOnly. |
|
38 $this->drupalLogin($user); |
|
39 $this->assertTrue(preg_match('/HttpOnly/i', $this->drupalGetHeader('Set-Cookie', TRUE)), 'Session cookie is set as HttpOnly.'); |
|
40 $this->drupalLogout(); |
|
41 |
|
42 // Verify that the session is regenerated if a module calls exit |
|
43 // in hook_user_login(). |
|
44 user_save($user, array('name' => 'session_test_user')); |
|
45 $user->name = 'session_test_user'; |
|
46 $this->drupalGet('session-test/id'); |
|
47 $matches = array(); |
|
48 preg_match('/\s*session_id:(.*)\n/', $this->drupalGetContent(), $matches); |
|
49 $this->assertTrue(!empty($matches[1]) , 'Found session ID before logging in.'); |
|
50 $original_session = $matches[1]; |
|
51 |
|
52 // We cannot use $this->drupalLogin($user); because we exit in |
|
53 // session_test_user_login() which breaks a normal assertion. |
|
54 $edit = array( |
|
55 'name' => $user->name, |
|
56 'pass' => $user->pass_raw |
|
57 ); |
|
58 $this->drupalPost('user', $edit, t('Log in')); |
|
59 $this->drupalGet('user'); |
|
60 $pass = $this->assertText($user->name, format_string('Found name: %name', array('%name' => $user->name)), 'User login'); |
|
61 $this->_logged_in = $pass; |
|
62 |
|
63 $this->drupalGet('session-test/id'); |
|
64 $matches = array(); |
|
65 preg_match('/\s*session_id:(.*)\n/', $this->drupalGetContent(), $matches); |
|
66 $this->assertTrue(!empty($matches[1]) , 'Found session ID after logging in.'); |
|
67 $this->assertTrue($matches[1] != $original_session, 'Session ID changed after login.'); |
|
68 } |
|
69 |
|
70 /** |
|
71 * Test data persistence via the session_test module callbacks. |
|
72 */ |
|
73 function testDataPersistence() { |
|
74 $user = $this->drupalCreateUser(array('access content')); |
|
75 // Enable sessions. |
|
76 $this->sessionReset($user->uid); |
|
77 |
|
78 $this->drupalLogin($user); |
|
79 |
|
80 $value_1 = $this->randomName(); |
|
81 $this->drupalGet('session-test/set/' . $value_1); |
|
82 $this->assertText($value_1, 'The session value was stored.', 'Session'); |
|
83 $this->drupalGet('session-test/get'); |
|
84 $this->assertText($value_1, 'Session correctly returned the stored data for an authenticated user.', 'Session'); |
|
85 |
|
86 // Attempt to write over val_1. If drupal_save_session(FALSE) is working. |
|
87 // properly, val_1 will still be set. |
|
88 $value_2 = $this->randomName(); |
|
89 $this->drupalGet('session-test/no-set/' . $value_2); |
|
90 $this->assertText($value_2, 'The session value was correctly passed to session-test/no-set.', 'Session'); |
|
91 $this->drupalGet('session-test/get'); |
|
92 $this->assertText($value_1, 'Session data is not saved for drupal_save_session(FALSE).', 'Session'); |
|
93 |
|
94 // Switch browser cookie to anonymous user, then back to user 1. |
|
95 $this->sessionReset(); |
|
96 $this->sessionReset($user->uid); |
|
97 $this->assertText($value_1, 'Session data persists through browser close.', 'Session'); |
|
98 |
|
99 // Logout the user and make sure the stored value no longer persists. |
|
100 $this->drupalLogout(); |
|
101 $this->sessionReset(); |
|
102 $this->drupalGet('session-test/get'); |
|
103 $this->assertNoText($value_1, "After logout, previous user's session data is not available.", 'Session'); |
|
104 |
|
105 // Now try to store some data as an anonymous user. |
|
106 $value_3 = $this->randomName(); |
|
107 $this->drupalGet('session-test/set/' . $value_3); |
|
108 $this->assertText($value_3, 'Session data stored for anonymous user.', 'Session'); |
|
109 $this->drupalGet('session-test/get'); |
|
110 $this->assertText($value_3, 'Session correctly returned the stored data for an anonymous user.', 'Session'); |
|
111 |
|
112 // Try to store data when drupal_save_session(FALSE). |
|
113 $value_4 = $this->randomName(); |
|
114 $this->drupalGet('session-test/no-set/' . $value_4); |
|
115 $this->assertText($value_4, 'The session value was correctly passed to session-test/no-set.', 'Session'); |
|
116 $this->drupalGet('session-test/get'); |
|
117 $this->assertText($value_3, 'Session data is not saved for drupal_save_session(FALSE).', 'Session'); |
|
118 |
|
119 // Login, the data should persist. |
|
120 $this->drupalLogin($user); |
|
121 $this->sessionReset($user->uid); |
|
122 $this->drupalGet('session-test/get'); |
|
123 $this->assertNoText($value_1, 'Session has persisted for an authenticated user after logging out and then back in.', 'Session'); |
|
124 |
|
125 // Change session and create another user. |
|
126 $user2 = $this->drupalCreateUser(array('access content')); |
|
127 $this->sessionReset($user2->uid); |
|
128 $this->drupalLogin($user2); |
|
129 } |
|
130 |
|
131 /** |
|
132 * Test that empty anonymous sessions are destroyed. |
|
133 */ |
|
134 function testEmptyAnonymousSession() { |
|
135 // Verify that no session is automatically created for anonymous user. |
|
136 $this->drupalGet(''); |
|
137 $this->assertSessionCookie(FALSE); |
|
138 $this->assertSessionEmpty(TRUE); |
|
139 |
|
140 // The same behavior is expected when caching is enabled. |
|
141 variable_set('cache', 1); |
|
142 $this->drupalGet(''); |
|
143 $this->assertSessionCookie(FALSE); |
|
144 $this->assertSessionEmpty(TRUE); |
|
145 $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.'); |
|
146 |
|
147 // Start a new session by setting a message. |
|
148 $this->drupalGet('session-test/set-message'); |
|
149 $this->assertSessionCookie(TRUE); |
|
150 $this->assertTrue($this->drupalGetHeader('Set-Cookie'), 'New session was started.'); |
|
151 |
|
152 // Display the message, during the same request the session is destroyed |
|
153 // and the session cookie is unset. |
|
154 $this->drupalGet(''); |
|
155 $this->assertSessionCookie(FALSE); |
|
156 $this->assertSessionEmpty(FALSE); |
|
157 $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Caching was bypassed.'); |
|
158 $this->assertText(t('This is a dummy message.'), 'Message was displayed.'); |
|
159 $this->assertTrue(preg_match('/SESS\w+=deleted/', $this->drupalGetHeader('Set-Cookie')), 'Session cookie was deleted.'); |
|
160 |
|
161 // Verify that session was destroyed. |
|
162 $this->drupalGet(''); |
|
163 $this->assertSessionCookie(FALSE); |
|
164 $this->assertSessionEmpty(TRUE); |
|
165 $this->assertNoText(t('This is a dummy message.'), 'Message was not cached.'); |
|
166 $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.'); |
|
167 $this->assertFalse($this->drupalGetHeader('Set-Cookie'), 'New session was not started.'); |
|
168 |
|
169 // Verify that no session is created if drupal_save_session(FALSE) is called. |
|
170 $this->drupalGet('session-test/set-message-but-dont-save'); |
|
171 $this->assertSessionCookie(FALSE); |
|
172 $this->assertSessionEmpty(TRUE); |
|
173 |
|
174 // Verify that no message is displayed. |
|
175 $this->drupalGet(''); |
|
176 $this->assertSessionCookie(FALSE); |
|
177 $this->assertSessionEmpty(TRUE); |
|
178 $this->assertNoText(t('This is a dummy message.'), 'The message was not saved.'); |
|
179 } |
|
180 |
|
181 /** |
|
182 * Test that sessions are only saved when necessary. |
|
183 */ |
|
184 function testSessionWrite() { |
|
185 $user = $this->drupalCreateUser(array('access content')); |
|
186 $this->drupalLogin($user); |
|
187 |
|
188 $sql = 'SELECT u.access, s.timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE u.uid = :uid'; |
|
189 $times1 = db_query($sql, array(':uid' => $user->uid))->fetchObject(); |
|
190 |
|
191 // Before every request we sleep one second to make sure that if the session |
|
192 // is saved, its timestamp will change. |
|
193 |
|
194 // Modify the session. |
|
195 sleep(1); |
|
196 $this->drupalGet('session-test/set/foo'); |
|
197 $times2 = db_query($sql, array(':uid' => $user->uid))->fetchObject(); |
|
198 $this->assertEqual($times2->access, $times1->access, 'Users table was not updated.'); |
|
199 $this->assertNotEqual($times2->timestamp, $times1->timestamp, 'Sessions table was updated.'); |
|
200 |
|
201 // Write the same value again, i.e. do not modify the session. |
|
202 sleep(1); |
|
203 $this->drupalGet('session-test/set/foo'); |
|
204 $times3 = db_query($sql, array(':uid' => $user->uid))->fetchObject(); |
|
205 $this->assertEqual($times3->access, $times1->access, 'Users table was not updated.'); |
|
206 $this->assertEqual($times3->timestamp, $times2->timestamp, 'Sessions table was not updated.'); |
|
207 |
|
208 // Do not change the session. |
|
209 sleep(1); |
|
210 $this->drupalGet(''); |
|
211 $times4 = db_query($sql, array(':uid' => $user->uid))->fetchObject(); |
|
212 $this->assertEqual($times4->access, $times3->access, 'Users table was not updated.'); |
|
213 $this->assertEqual($times4->timestamp, $times3->timestamp, 'Sessions table was not updated.'); |
|
214 |
|
215 // Force updating of users and sessions table once per second. |
|
216 variable_set('session_write_interval', 0); |
|
217 $this->drupalGet(''); |
|
218 $times5 = db_query($sql, array(':uid' => $user->uid))->fetchObject(); |
|
219 $this->assertNotEqual($times5->access, $times4->access, 'Users table was updated.'); |
|
220 $this->assertNotEqual($times5->timestamp, $times4->timestamp, 'Sessions table was updated.'); |
|
221 } |
|
222 |
|
223 /** |
|
224 * Test that empty session IDs are not allowed. |
|
225 */ |
|
226 function testEmptySessionID() { |
|
227 $user = $this->drupalCreateUser(array('access content')); |
|
228 $this->drupalLogin($user); |
|
229 $this->drupalGet('session-test/is-logged-in'); |
|
230 $this->assertResponse(200, 'User is logged in.'); |
|
231 |
|
232 // Reset the sid in {sessions} to a blank string. This may exist in the |
|
233 // wild in some cases, although we normally prevent it from happening. |
|
234 db_query("UPDATE {sessions} SET sid = '' WHERE uid = :uid", array(':uid' => $user->uid)); |
|
235 // Send a blank sid in the session cookie, and the session should no longer |
|
236 // be valid. Closing the curl handler will stop the previous session ID |
|
237 // from persisting. |
|
238 $this->curlClose(); |
|
239 $this->additionalCurlOptions[CURLOPT_COOKIE] = rawurlencode($this->session_name) . '=;'; |
|
240 $this->drupalGet('session-test/id-from-cookie'); |
|
241 $this->assertRaw("session_id:\n", 'Session ID is blank as sent from cookie header.'); |
|
242 // Assert that we have an anonymous session now. |
|
243 $this->drupalGet('session-test/is-logged-in'); |
|
244 $this->assertResponse(403, 'An empty session ID is not allowed.'); |
|
245 } |
|
246 |
|
247 /** |
|
248 * Reset the cookie file so that it refers to the specified user. |
|
249 * |
|
250 * @param $uid User id to set as the active session. |
|
251 */ |
|
252 function sessionReset($uid = 0) { |
|
253 // Close the internal browser. |
|
254 $this->curlClose(); |
|
255 $this->loggedInUser = FALSE; |
|
256 |
|
257 // Change cookie file for user. |
|
258 $this->cookieFile = file_stream_wrapper_get_instance_by_scheme('temporary')->getDirectoryPath() . '/cookie.' . $uid . '.txt'; |
|
259 $this->additionalCurlOptions[CURLOPT_COOKIEFILE] = $this->cookieFile; |
|
260 $this->additionalCurlOptions[CURLOPT_COOKIESESSION] = TRUE; |
|
261 $this->drupalGet('session-test/get'); |
|
262 $this->assertResponse(200, 'Session test module is correctly enabled.', 'Session'); |
|
263 } |
|
264 |
|
265 /** |
|
266 * Assert whether the SimpleTest browser sent a session cookie. |
|
267 */ |
|
268 function assertSessionCookie($sent) { |
|
269 if ($sent) { |
|
270 $this->assertNotNull($this->session_id, 'Session cookie was sent.'); |
|
271 } |
|
272 else { |
|
273 $this->assertNull($this->session_id, 'Session cookie was not sent.'); |
|
274 } |
|
275 } |
|
276 |
|
277 /** |
|
278 * Assert whether $_SESSION is empty at the beginning of the request. |
|
279 */ |
|
280 function assertSessionEmpty($empty) { |
|
281 if ($empty) { |
|
282 $this->assertIdentical($this->drupalGetHeader('X-Session-Empty'), '1', 'Session was empty.'); |
|
283 } |
|
284 else { |
|
285 $this->assertIdentical($this->drupalGetHeader('X-Session-Empty'), '0', 'Session was not empty.'); |
|
286 } |
|
287 } |
|
288 } |
|
289 |
|
290 /** |
|
291 * Ensure that when running under HTTPS two session cookies are generated. |
|
292 */ |
|
293 class SessionHttpsTestCase extends DrupalWebTestCase { |
|
294 |
|
295 public static function getInfo() { |
|
296 return array( |
|
297 'name' => 'Session HTTPS handling', |
|
298 'description' => 'Ensure that when running under HTTPS two session cookies are generated.', |
|
299 'group' => 'Session' |
|
300 ); |
|
301 } |
|
302 |
|
303 public function setUp() { |
|
304 parent::setUp('session_test'); |
|
305 } |
|
306 |
|
307 protected function testHttpsSession() { |
|
308 global $is_https; |
|
309 |
|
310 if ($is_https) { |
|
311 $secure_session_name = session_name(); |
|
312 $insecure_session_name = substr(session_name(), 1); |
|
313 } |
|
314 else { |
|
315 $secure_session_name = 'S' . session_name(); |
|
316 $insecure_session_name = session_name(); |
|
317 } |
|
318 |
|
319 $user = $this->drupalCreateUser(array('access administration pages')); |
|
320 |
|
321 // Test HTTPS session handling by altering the form action to submit the |
|
322 // login form through https.php, which creates a mock HTTPS request. |
|
323 $this->drupalGet('user'); |
|
324 $form = $this->xpath('//form[@id="user-login"]'); |
|
325 $form[0]['action'] = $this->httpsUrl('user'); |
|
326 $edit = array('name' => $user->name, 'pass' => $user->pass_raw); |
|
327 $this->drupalPost(NULL, $edit, t('Log in')); |
|
328 |
|
329 // Test a second concurrent session. |
|
330 $this->curlClose(); |
|
331 $this->drupalGet('user'); |
|
332 $form = $this->xpath('//form[@id="user-login"]'); |
|
333 $form[0]['action'] = $this->httpsUrl('user'); |
|
334 $this->drupalPost(NULL, $edit, t('Log in')); |
|
335 |
|
336 // Check secure cookie on secure page. |
|
337 $this->assertTrue($this->cookies[$secure_session_name]['secure'], 'The secure cookie has the secure attribute'); |
|
338 // Check insecure cookie is not set. |
|
339 $this->assertFalse(isset($this->cookies[$insecure_session_name])); |
|
340 $ssid = $this->cookies[$secure_session_name]['value']; |
|
341 $this->assertSessionIds($ssid, $ssid, 'Session has a non-empty SID and a correct secure SID.'); |
|
342 $cookie = $secure_session_name . '=' . $ssid; |
|
343 |
|
344 // Verify that user is logged in on secure URL. |
|
345 $this->curlClose(); |
|
346 $this->drupalGet($this->httpsUrl('admin/config'), array(), array('Cookie: ' . $cookie)); |
|
347 $this->assertText(t('Configuration')); |
|
348 $this->assertResponse(200); |
|
349 |
|
350 // Verify that user is not logged in on non-secure URL. |
|
351 $this->curlClose(); |
|
352 $this->drupalGet($this->httpUrl('admin/config'), array(), array('Cookie: ' . $cookie)); |
|
353 $this->assertNoText(t('Configuration')); |
|
354 $this->assertResponse(403); |
|
355 |
|
356 // Verify that empty SID cannot be used on the non-secure site. |
|
357 $this->curlClose(); |
|
358 $cookie = $insecure_session_name . '='; |
|
359 $this->drupalGet($this->httpUrl('admin/config'), array(), array('Cookie: ' . $cookie)); |
|
360 $this->assertResponse(403); |
|
361 |
|
362 // Test HTTP session handling by altering the form action to submit the |
|
363 // login form through http.php, which creates a mock HTTP request on HTTPS |
|
364 // test environments. |
|
365 $this->curlClose(); |
|
366 $this->drupalGet('user'); |
|
367 $form = $this->xpath('//form[@id="user-login"]'); |
|
368 $form[0]['action'] = $this->httpUrl('user'); |
|
369 $edit = array('name' => $user->name, 'pass' => $user->pass_raw); |
|
370 $this->drupalPost(NULL, $edit, t('Log in')); |
|
371 $this->drupalGet($this->httpUrl('admin/config')); |
|
372 $this->assertResponse(200); |
|
373 $sid = $this->cookies[$insecure_session_name]['value']; |
|
374 $this->assertSessionIds($sid, '', 'Session has the correct SID and an empty secure SID.'); |
|
375 |
|
376 // Verify that empty secure SID cannot be used on the secure site. |
|
377 $this->curlClose(); |
|
378 $cookie = $secure_session_name . '='; |
|
379 $this->drupalGet($this->httpsUrl('admin/config'), array(), array('Cookie: ' . $cookie)); |
|
380 $this->assertResponse(403); |
|
381 |
|
382 // Clear browser cookie jar. |
|
383 $this->cookies = array(); |
|
384 |
|
385 if ($is_https) { |
|
386 // The functionality does not make sense when running on HTTPS. |
|
387 return; |
|
388 } |
|
389 |
|
390 // Enable secure pages. |
|
391 variable_set('https', TRUE); |
|
392 |
|
393 $this->curlClose(); |
|
394 // Start an anonymous session on the insecure site. |
|
395 $session_data = $this->randomName(); |
|
396 $this->drupalGet('session-test/set/' . $session_data); |
|
397 // Check secure cookie on insecure page. |
|
398 $this->assertFalse(isset($this->cookies[$secure_session_name]), 'The secure cookie is not sent on insecure pages.'); |
|
399 // Check insecure cookie on insecure page. |
|
400 $this->assertFalse($this->cookies[$insecure_session_name]['secure'], 'The insecure cookie does not have the secure attribute'); |
|
401 |
|
402 // Store the anonymous cookie so we can validate that its session is killed |
|
403 // after login. |
|
404 $anonymous_cookie = $insecure_session_name . '=' . $this->cookies[$insecure_session_name]['value']; |
|
405 |
|
406 // Check that password request form action is not secure. |
|
407 $this->drupalGet('user/password'); |
|
408 $form = $this->xpath('//form[@id="user-pass"]'); |
|
409 $this->assertNotEqual(substr($form[0]['action'], 0, 6), 'https:', 'Password request form action is not secure'); |
|
410 $form[0]['action'] = $this->httpsUrl('user'); |
|
411 |
|
412 // Check that user login form action is secure. |
|
413 $this->drupalGet('user'); |
|
414 $form = $this->xpath('//form[@id="user-login"]'); |
|
415 $this->assertEqual(substr($form[0]['action'], 0, 6), 'https:', 'Login form action is secure'); |
|
416 $form[0]['action'] = $this->httpsUrl('user'); |
|
417 |
|
418 $edit = array( |
|
419 'name' => $user->name, |
|
420 'pass' => $user->pass_raw, |
|
421 ); |
|
422 $this->drupalPost(NULL, $edit, t('Log in')); |
|
423 // Check secure cookie on secure page. |
|
424 $this->assertTrue($this->cookies[$secure_session_name]['secure'], 'The secure cookie has the secure attribute'); |
|
425 // Check insecure cookie on secure page. |
|
426 $this->assertFalse($this->cookies[$insecure_session_name]['secure'], 'The insecure cookie does not have the secure attribute'); |
|
427 |
|
428 $sid = $this->cookies[$insecure_session_name]['value']; |
|
429 $ssid = $this->cookies[$secure_session_name]['value']; |
|
430 $this->assertSessionIds($sid, $ssid, 'Session has both secure and insecure SIDs'); |
|
431 $cookies = array( |
|
432 $insecure_session_name . '=' . $sid, |
|
433 $secure_session_name . '=' . $ssid, |
|
434 ); |
|
435 |
|
436 // Test that session data saved before login is still available on the |
|
437 // authenticated session. |
|
438 $this->drupalGet('session-test/get'); |
|
439 $this->assertText($session_data, 'Session correctly returned the stored data set by the anonymous session.'); |
|
440 |
|
441 foreach ($cookies as $cookie_key => $cookie) { |
|
442 foreach (array('admin/config', $this->httpsUrl('admin/config')) as $url_key => $url) { |
|
443 $this->curlClose(); |
|
444 |
|
445 $this->drupalGet($url, array(), array('Cookie: ' . $cookie)); |
|
446 if ($cookie_key == $url_key) { |
|
447 $this->assertText(t('Configuration')); |
|
448 $this->assertResponse(200); |
|
449 } |
|
450 else { |
|
451 $this->assertNoText(t('Configuration')); |
|
452 $this->assertResponse(403); |
|
453 } |
|
454 } |
|
455 } |
|
456 |
|
457 // Test that session data saved before login is not available using the |
|
458 // pre-login anonymous cookie. |
|
459 $this->cookies = array(); |
|
460 $this->drupalGet('session-test/get', array('Cookie: ' . $anonymous_cookie)); |
|
461 $this->assertNoText($session_data, 'Initial anonymous session is inactive after login.'); |
|
462 |
|
463 // Clear browser cookie jar. |
|
464 $this->cookies = array(); |
|
465 |
|
466 // Start an anonymous session on the secure site. |
|
467 $this->drupalGet($this->httpsUrl('session-test/set/1')); |
|
468 |
|
469 // Mock a login to the secure site using the secure session cookie. |
|
470 $this->drupalGet('user'); |
|
471 $form = $this->xpath('//form[@id="user-login"]'); |
|
472 $form[0]['action'] = $this->httpsUrl('user'); |
|
473 $this->drupalPost(NULL, $edit, t('Log in')); |
|
474 |
|
475 // Test that the user is also authenticated on the insecure site. |
|
476 $this->drupalGet("user/{$user->uid}/edit"); |
|
477 $this->assertResponse(200); |
|
478 } |
|
479 |
|
480 /** |
|
481 * Tests that empty session IDs do not cause unrelated sessions to load. |
|
482 */ |
|
483 public function testEmptySessionId() { |
|
484 global $is_https; |
|
485 |
|
486 if ($is_https) { |
|
487 $secure_session_name = session_name(); |
|
488 } |
|
489 else { |
|
490 $secure_session_name = 'S' . session_name(); |
|
491 } |
|
492 |
|
493 // Enable mixed mode for HTTP and HTTPS. |
|
494 variable_set('https', TRUE); |
|
495 |
|
496 $admin_user = $this->drupalCreateUser(array('access administration pages')); |
|
497 $standard_user = $this->drupalCreateUser(array('access content')); |
|
498 |
|
499 // First log in as the admin user on HTTP. |
|
500 // We cannot use $this->drupalLogin() here because we need to use the |
|
501 // special http.php URLs. |
|
502 $edit = array( |
|
503 'name' => $admin_user->name, |
|
504 'pass' => $admin_user->pass_raw |
|
505 ); |
|
506 $this->drupalGet('user'); |
|
507 $form = $this->xpath('//form[@id="user-login"]'); |
|
508 $form[0]['action'] = $this->httpUrl('user'); |
|
509 $this->drupalPost(NULL, $edit, t('Log in')); |
|
510 |
|
511 $this->curlClose(); |
|
512 |
|
513 // Now start a session for the standard user on HTTPS. |
|
514 $edit = array( |
|
515 'name' => $standard_user->name, |
|
516 'pass' => $standard_user->pass_raw |
|
517 ); |
|
518 $this->drupalGet('user'); |
|
519 $form = $this->xpath('//form[@id="user-login"]'); |
|
520 $form[0]['action'] = $this->httpsUrl('user'); |
|
521 $this->drupalPost(NULL, $edit, t('Log in')); |
|
522 |
|
523 // Make the secure session cookie blank. |
|
524 curl_setopt($this->curlHandle, CURLOPT_COOKIE, "$secure_session_name="); |
|
525 $this->drupalGet($this->httpsUrl('user')); |
|
526 $this->assertNoText($admin_user->name, 'User is not logged in as admin'); |
|
527 $this->assertNoText($standard_user->name, "The user's own name is not displayed because the invalid session cookie has logged them out."); |
|
528 } |
|
529 |
|
530 /** |
|
531 * Test that there exists a session with two specific session IDs. |
|
532 * |
|
533 * @param $sid |
|
534 * The insecure session ID to search for. |
|
535 * @param $ssid |
|
536 * The secure session ID to search for. |
|
537 * @param $assertion_text |
|
538 * The text to display when we perform the assertion. |
|
539 * |
|
540 * @return |
|
541 * The result of assertTrue() that there's a session in the system that |
|
542 * has the given insecure and secure session IDs. |
|
543 */ |
|
544 protected function assertSessionIds($sid, $ssid, $assertion_text) { |
|
545 $args = array( |
|
546 ':sid' => $sid, |
|
547 ':ssid' => $ssid, |
|
548 ); |
|
549 return $this->assertTrue(db_query('SELECT timestamp FROM {sessions} WHERE sid = :sid AND ssid = :ssid', $args)->fetchField(), $assertion_text); |
|
550 } |
|
551 |
|
552 /** |
|
553 * Builds a URL for submitting a mock HTTPS request to HTTP test environments. |
|
554 * |
|
555 * @param $url |
|
556 * A Drupal path such as 'user'. |
|
557 * |
|
558 * @return |
|
559 * An absolute URL. |
|
560 */ |
|
561 protected function httpsUrl($url) { |
|
562 global $base_url; |
|
563 return $base_url . '/modules/simpletest/tests/https.php?q=' . $url; |
|
564 } |
|
565 |
|
566 /** |
|
567 * Builds a URL for submitting a mock HTTP request to HTTPS test environments. |
|
568 * |
|
569 * @param $url |
|
570 * A Drupal path such as 'user'. |
|
571 * |
|
572 * @return |
|
573 * An absolute URL. |
|
574 */ |
|
575 protected function httpUrl($url) { |
|
576 global $base_url; |
|
577 return $base_url . '/modules/simpletest/tests/http.php?q=' . $url; |
|
578 } |
|
579 } |
|
580 |