websocket_stream_cookie_test.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <string>
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/memory/weak_ptr.h"
  8. #include "base/run_loop.h"
  9. #include "base/strings/string_util.h"
  10. #include "base/strings/stringprintf.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "net/base/isolation_info.h"
  13. #include "net/cookies/canonical_cookie.h"
  14. #include "net/cookies/canonical_cookie_test_helpers.h"
  15. #include "net/cookies/cookie_access_result.h"
  16. #include "net/cookies/cookie_store.h"
  17. #include "net/cookies/cookie_util.h"
  18. #include "net/http/http_request_headers.h"
  19. #include "net/socket/socket_test_util.h"
  20. #include "net/websockets/websocket_stream_create_test_base.h"
  21. #include "net/websockets/websocket_test_util.h"
  22. #include "testing/gmock/include/gmock/gmock.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. #include "url/gurl.h"
  25. #include "url/origin.h"
  26. namespace net {
  27. namespace {
  28. using ::testing::TestWithParam;
  29. using ::testing::ValuesIn;
  30. const WebSocketExtraHeaders kNoCookieHeader = {};
  31. class TestBase : public WebSocketStreamCreateTestBase {
  32. public:
  33. void CreateAndConnect(const GURL& url,
  34. const url::Origin& origin,
  35. const SiteForCookies& site_for_cookies,
  36. const IsolationInfo& isolation_info,
  37. const WebSocketExtraHeaders& cookie_header,
  38. const std::string& response_body) {
  39. url_request_context_host_.SetExpectations(
  40. WebSocketStandardRequestWithCookies(
  41. url.path(), url.host(), origin, cookie_header,
  42. /*send_additional_request_headers=*/{}, /*extra_headers=*/{}),
  43. response_body);
  44. CreateAndConnectStream(url, NoSubProtocols(), origin, site_for_cookies,
  45. isolation_info, HttpRequestHeaders(), nullptr);
  46. }
  47. };
  48. struct ClientUseCookieParameter {
  49. // The URL for the WebSocket connection.
  50. const char* const url;
  51. // The URL for the previously set cookies.
  52. const char* const cookie_url;
  53. // The previously set cookies contents.
  54. const char* const cookie_line;
  55. // The Cookie: HTTP header expected to appear in the WS request.
  56. const WebSocketExtraHeaders cookie_header;
  57. };
  58. class WebSocketStreamClientUseCookieTest
  59. : public TestBase,
  60. public TestWithParam<ClientUseCookieParameter> {
  61. public:
  62. ~WebSocketStreamClientUseCookieTest() override {
  63. // Permit any endpoint locks to be released.
  64. stream_request_.reset();
  65. stream_.reset();
  66. base::RunLoop().RunUntilIdle();
  67. }
  68. static void SetCookieHelperFunction(const base::RepeatingClosure& task,
  69. base::WeakPtr<bool> weak_is_called,
  70. base::WeakPtr<bool> weak_result,
  71. CookieAccessResult access_result) {
  72. *weak_is_called = true;
  73. *weak_result = access_result.status.IsInclude();
  74. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
  75. }
  76. };
  77. struct ServerSetCookieParameter {
  78. // The URL for the WebSocket connection.
  79. const char* const url;
  80. // The URL used to query cookies after the response received.
  81. const char* const cookie_url;
  82. // The cookies expected to appear for |cookie_url| inquiry.
  83. const char* const cookie_line;
  84. // The Set-Cookie: HTTP header attached to the response.
  85. const WebSocketExtraHeaders cookie_header;
  86. };
  87. class WebSocketStreamServerSetCookieTest
  88. : public TestBase,
  89. public TestWithParam<ServerSetCookieParameter> {
  90. public:
  91. ~WebSocketStreamServerSetCookieTest() override {
  92. // Permit any endpoint locks to be released.
  93. stream_request_.reset();
  94. stream_.reset();
  95. base::RunLoop().RunUntilIdle();
  96. }
  97. static void GetCookieListHelperFunction(
  98. base::OnceClosure task,
  99. base::WeakPtr<bool> weak_is_called,
  100. base::WeakPtr<CookieList> weak_result,
  101. const CookieAccessResultList& cookie_list,
  102. const CookieAccessResultList& excluded_cookies) {
  103. *weak_is_called = true;
  104. *weak_result = cookie_util::StripAccessResults(cookie_list);
  105. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
  106. }
  107. };
  108. TEST_P(WebSocketStreamClientUseCookieTest, ClientUseCookie) {
  109. // For wss tests.
  110. url_request_context_host_.AddSSLSocketDataProvider(
  111. std::make_unique<SSLSocketDataProvider>(ASYNC, OK));
  112. CookieStore* store =
  113. url_request_context_host_.GetURLRequestContext()->cookie_store();
  114. const GURL url(GetParam().url);
  115. const GURL cookie_url(GetParam().cookie_url);
  116. const url::Origin origin = url::Origin::Create(GURL(GetParam().url));
  117. const SiteForCookies site_for_cookies = SiteForCookies::FromOrigin(origin);
  118. const IsolationInfo isolation_info =
  119. IsolationInfo::Create(IsolationInfo::RequestType::kOther, origin, origin,
  120. SiteForCookies::FromOrigin(origin));
  121. const std::string cookie_line(GetParam().cookie_line);
  122. bool is_called = false;
  123. bool set_cookie_result = false;
  124. base::WeakPtrFactory<bool> weak_is_called(&is_called);
  125. base::WeakPtrFactory<bool> weak_set_cookie_result(&set_cookie_result);
  126. base::RunLoop run_loop;
  127. auto cookie =
  128. CanonicalCookie::Create(cookie_url, cookie_line, base::Time::Now(),
  129. absl::nullopt /* server_time */,
  130. absl::nullopt /* cookie_partition_key */);
  131. store->SetCanonicalCookieAsync(
  132. std::move(cookie), cookie_url, net::CookieOptions::MakeAllInclusive(),
  133. base::BindOnce(&SetCookieHelperFunction, run_loop.QuitClosure(),
  134. weak_is_called.GetWeakPtr(),
  135. weak_set_cookie_result.GetWeakPtr()));
  136. run_loop.Run();
  137. ASSERT_TRUE(is_called);
  138. ASSERT_TRUE(set_cookie_result);
  139. CreateAndConnect(url, origin, site_for_cookies, isolation_info,
  140. GetParam().cookie_header, WebSocketStandardResponse(""));
  141. WaitUntilConnectDone();
  142. EXPECT_FALSE(has_failed());
  143. }
  144. TEST_P(WebSocketStreamServerSetCookieTest, ServerSetCookie) {
  145. // For wss tests.
  146. url_request_context_host_.AddSSLSocketDataProvider(
  147. std::make_unique<SSLSocketDataProvider>(ASYNC, OK));
  148. const GURL url(GetParam().url);
  149. const GURL cookie_url(GetParam().cookie_url);
  150. const url::Origin origin = url::Origin::Create(GURL(GetParam().url));
  151. const SiteForCookies site_for_cookies = SiteForCookies::FromOrigin(origin);
  152. const IsolationInfo isolation_info =
  153. IsolationInfo::Create(IsolationInfo::RequestType::kOther, origin, origin,
  154. SiteForCookies::FromOrigin(origin));
  155. const std::string cookie_line(GetParam().cookie_line);
  156. HttpRequestHeaders headers;
  157. for (const auto& [key, value] : GetParam().cookie_header)
  158. headers.SetHeader(key, value);
  159. std::string cookie_header(headers.ToString());
  160. const std::string response = base::StringPrintf(
  161. "HTTP/1.1 101 Switching Protocols\r\n"
  162. "Upgrade: websocket\r\n"
  163. "Connection: Upgrade\r\n"
  164. "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
  165. "%s",
  166. cookie_header.c_str());
  167. CookieStore* store =
  168. url_request_context_host_.GetURLRequestContext()->cookie_store();
  169. CreateAndConnect(url, origin, site_for_cookies, isolation_info,
  170. /*cookie_header=*/{}, response);
  171. WaitUntilConnectDone();
  172. EXPECT_FALSE(has_failed()) << failure_message();
  173. bool is_called = false;
  174. CookieList get_cookie_list_result;
  175. base::WeakPtrFactory<bool> weak_is_called(&is_called);
  176. base::WeakPtrFactory<CookieList> weak_get_cookie_list_result(
  177. &get_cookie_list_result);
  178. base::RunLoop run_loop;
  179. store->GetCookieListWithOptionsAsync(
  180. cookie_url, net::CookieOptions::MakeAllInclusive(),
  181. CookiePartitionKeyCollection(),
  182. base::BindOnce(&GetCookieListHelperFunction, run_loop.QuitClosure(),
  183. weak_is_called.GetWeakPtr(),
  184. weak_get_cookie_list_result.GetWeakPtr()));
  185. run_loop.Run();
  186. EXPECT_TRUE(is_called);
  187. EXPECT_THAT(get_cookie_list_result, MatchesCookieLine(cookie_line));
  188. }
  189. // Test parameters definitions follow...
  190. const ClientUseCookieParameter kClientUseCookieParameters[] = {
  191. // Non-secure cookies for ws
  192. {"ws://www.example.com",
  193. "http://www.example.com",
  194. "test-cookie",
  195. {{"Cookie", "test-cookie"}}},
  196. {"ws://www.example.com",
  197. "https://www.example.com",
  198. "test-cookie",
  199. {{"Cookie", "test-cookie"}}},
  200. {"ws://www.example.com",
  201. "ws://www.example.com",
  202. "test-cookie",
  203. {{"Cookie", "test-cookie"}}},
  204. {"ws://www.example.com",
  205. "wss://www.example.com",
  206. "test-cookie",
  207. {{"Cookie", "test-cookie"}}},
  208. // Non-secure cookies for wss
  209. {"wss://www.example.com",
  210. "http://www.example.com",
  211. "test-cookie",
  212. {{"Cookie", "test-cookie"}}},
  213. {"wss://www.example.com",
  214. "https://www.example.com",
  215. "test-cookie",
  216. {{"Cookie", "test-cookie"}}},
  217. {"wss://www.example.com",
  218. "ws://www.example.com",
  219. "test-cookie",
  220. {{"Cookie", "test-cookie"}}},
  221. {"wss://www.example.com",
  222. "wss://www.example.com",
  223. "test-cookie",
  224. {{"Cookie", "test-cookie"}}},
  225. // Secure-cookies for ws
  226. {"ws://www.example.com", "https://www.example.com", "test-cookie; secure",
  227. kNoCookieHeader},
  228. {"ws://www.example.com", "wss://www.example.com", "test-cookie; secure",
  229. kNoCookieHeader},
  230. // Secure-cookies for wss
  231. {"wss://www.example.com",
  232. "https://www.example.com",
  233. "test-cookie; secure",
  234. {{"Cookie", "test-cookie"}}},
  235. {"wss://www.example.com",
  236. "wss://www.example.com",
  237. "test-cookie; secure",
  238. {{"Cookie", "test-cookie"}}},
  239. // Non-secure cookies for ws (sharing domain)
  240. {"ws://www.example.com",
  241. "http://www2.example.com",
  242. "test-cookie; Domain=example.com",
  243. {{"Cookie", "test-cookie"}}},
  244. {"ws://www.example.com",
  245. "https://www2.example.com",
  246. "test-cookie; Domain=example.com",
  247. {{"Cookie", "test-cookie"}}},
  248. {"ws://www.example.com",
  249. "ws://www2.example.com",
  250. "test-cookie; Domain=example.com",
  251. {{"Cookie", "test-cookie"}}},
  252. {"ws://www.example.com",
  253. "wss://www2.example.com",
  254. "test-cookie; Domain=example.com",
  255. {{"Cookie", "test-cookie"}}},
  256. // Non-secure cookies for wss (sharing domain)
  257. {"wss://www.example.com",
  258. "http://www2.example.com",
  259. "test-cookie; Domain=example.com",
  260. {{"Cookie", "test-cookie"}}},
  261. {"wss://www.example.com",
  262. "https://www2.example.com",
  263. "test-cookie; Domain=example.com",
  264. {{"Cookie", "test-cookie"}}},
  265. {"wss://www.example.com",
  266. "ws://www2.example.com",
  267. "test-cookie; Domain=example.com",
  268. {{"Cookie", "test-cookie"}}},
  269. {"wss://www.example.com",
  270. "wss://www2.example.com",
  271. "test-cookie; Domain=example.com",
  272. {{"Cookie", "test-cookie"}}},
  273. // Secure-cookies for ws (sharing domain)
  274. {"ws://www.example.com", "https://www2.example.com",
  275. "test-cookie; Domain=example.com; secure", kNoCookieHeader},
  276. {"ws://www.example.com", "wss://www2.example.com",
  277. "test-cookie; Domain=example.com; secure", kNoCookieHeader},
  278. // Secure-cookies for wss (sharing domain)
  279. {"wss://www.example.com",
  280. "https://www2.example.com",
  281. "test-cookie; Domain=example.com; secure",
  282. {{"Cookie", "test-cookie"}}},
  283. {"wss://www.example.com",
  284. "wss://www2.example.com",
  285. "test-cookie; Domain=example.com; secure",
  286. {{"Cookie", "test-cookie"}}},
  287. // Non-matching cookies for ws
  288. {"ws://www.example.com", "http://www2.example.com", "test-cookie",
  289. kNoCookieHeader},
  290. {"ws://www.example.com", "https://www2.example.com", "test-cookie",
  291. kNoCookieHeader},
  292. {"ws://www.example.com", "ws://www2.example.com", "test-cookie",
  293. kNoCookieHeader},
  294. {"ws://www.example.com", "wss://www2.example.com", "test-cookie",
  295. kNoCookieHeader},
  296. // Non-matching cookies for wss
  297. {"wss://www.example.com", "http://www2.example.com", "test-cookie",
  298. kNoCookieHeader},
  299. {"wss://www.example.com", "https://www2.example.com", "test-cookie",
  300. kNoCookieHeader},
  301. {"wss://www.example.com", "ws://www2.example.com", "test-cookie",
  302. kNoCookieHeader},
  303. {"wss://www.example.com", "wss://www2.example.com", "test-cookie",
  304. kNoCookieHeader},
  305. };
  306. INSTANTIATE_TEST_SUITE_P(WebSocketStreamClientUseCookieTest,
  307. WebSocketStreamClientUseCookieTest,
  308. ValuesIn(kClientUseCookieParameters));
  309. const ServerSetCookieParameter kServerSetCookieParameters[] = {
  310. // Cookies coming from ws
  311. {"ws://www.example.com",
  312. "http://www.example.com",
  313. "test-cookie",
  314. {{"Set-Cookie", "test-cookie"}}},
  315. {"ws://www.example.com",
  316. "https://www.example.com",
  317. "test-cookie",
  318. {{"Set-Cookie", "test-cookie"}}},
  319. {"ws://www.example.com",
  320. "ws://www.example.com",
  321. "test-cookie",
  322. {{"Set-Cookie", "test-cookie"}}},
  323. {"ws://www.example.com",
  324. "wss://www.example.com",
  325. "test-cookie",
  326. {{"Set-Cookie", "test-cookie"}}},
  327. // Cookies coming from wss
  328. {"wss://www.example.com",
  329. "http://www.example.com",
  330. "test-cookie",
  331. {{"Set-Cookie", "test-cookie"}}},
  332. {"wss://www.example.com",
  333. "https://www.example.com",
  334. "test-cookie",
  335. {{"Set-Cookie", "test-cookie"}}},
  336. {"wss://www.example.com",
  337. "ws://www.example.com",
  338. "test-cookie",
  339. {{"Set-Cookie", "test-cookie"}}},
  340. {"wss://www.example.com",
  341. "wss://www.example.com",
  342. "test-cookie",
  343. {{"Set-Cookie", "test-cookie"}}},
  344. // cookies coming from ws (sharing domain)
  345. {"ws://www.example.com",
  346. "http://www2.example.com",
  347. "test-cookie",
  348. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  349. {"ws://www.example.com",
  350. "https://www2.example.com",
  351. "test-cookie",
  352. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  353. {"ws://www.example.com",
  354. "ws://www2.example.com",
  355. "test-cookie",
  356. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  357. {"ws://www.example.com",
  358. "wss://www2.example.com",
  359. "test-cookie",
  360. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  361. // cookies coming from wss (sharing domain)
  362. {"wss://www.example.com",
  363. "http://www2.example.com",
  364. "test-cookie",
  365. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  366. {"wss://www.example.com",
  367. "https://www2.example.com",
  368. "test-cookie",
  369. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  370. {"wss://www.example.com",
  371. "ws://www2.example.com",
  372. "test-cookie",
  373. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  374. {"wss://www.example.com",
  375. "wss://www2.example.com",
  376. "test-cookie",
  377. {{"Set-Cookie", "test-cookie; Domain=example.com"}}},
  378. // Non-matching cookies coming from ws
  379. {"ws://www.example.com",
  380. "http://www2.example.com",
  381. "",
  382. {{"Set-Cookie", "test-cookie"}}},
  383. {"ws://www.example.com",
  384. "https://www2.example.com",
  385. "",
  386. {{"Set-Cookie", "test-cookie"}}},
  387. {"ws://www.example.com",
  388. "ws://www2.example.com",
  389. "",
  390. {{"Set-Cookie", "test-cookie"}}},
  391. {"ws://www.example.com",
  392. "wss://www2.example.com",
  393. "",
  394. {{"Set-Cookie", "test-cookie"}}},
  395. // Non-matching cookies coming from wss
  396. {"wss://www.example.com",
  397. "http://www2.example.com",
  398. "",
  399. {{"Set-Cookie", "test-cookie"}}},
  400. {"wss://www.example.com",
  401. "https://www2.example.com",
  402. "",
  403. {{"Set-Cookie", "test-cookie"}}},
  404. {"wss://www.example.com",
  405. "ws://www2.example.com",
  406. "",
  407. {{"Set-Cookie", "test-cookie"}}},
  408. {"wss://www.example.com",
  409. "wss://www2.example.com",
  410. "",
  411. {{"Set-Cookie", "test-cookie"}}},
  412. };
  413. INSTANTIATE_TEST_SUITE_P(WebSocketStreamServerSetCookieTest,
  414. WebSocketStreamServerSetCookieTest,
  415. ValuesIn(kServerSetCookieParameters));
  416. } // namespace
  417. } // namespace net