HttpServerTest.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "HttpServer.h"
  2. #include <cppunit/extensions/HelperMacros.h>
  3. #include "SocketCore.h"
  4. #include "a2functional.h"
  5. namespace aria2 {
  6. class HttpServerTest : public CppUnit::TestFixture
  7. {
  8. CPPUNIT_TEST_SUITE(HttpServerTest);
  9. CPPUNIT_TEST(testHttpBasicAuth);
  10. CPPUNIT_TEST_SUITE_END();
  11. public:
  12. void testHttpBasicAuth();
  13. };
  14. CPPUNIT_TEST_SUITE_REGISTRATION(HttpServerTest);
  15. namespace {
  16. std::unique_ptr<HttpServer> performHttpRequest(SocketCore& server, std::string request)
  17. {
  18. std::pair<std::string, uint16_t> addr;
  19. server.getAddrInfo(addr);
  20. SocketCore client;
  21. client.establishConnection("localhost", addr.second);
  22. while (!client.isWritable(0)) {}
  23. auto inbound = server.acceptConnection();
  24. inbound->setBlockingMode();
  25. auto rv = make_unique<HttpServer>(inbound);
  26. client.writeData(request);
  27. while (!rv->receiveRequest()) {}
  28. return rv;
  29. }
  30. } // namespace
  31. void HttpServerTest::testHttpBasicAuth()
  32. {
  33. SocketCore server;
  34. server.bind(0);
  35. server.beginListen();
  36. server.setBlockingMode();
  37. {
  38. // Default is no auth
  39. auto req = performHttpRequest(
  40. server, "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\n\r\n");
  41. CPPUNIT_ASSERT(req->authenticate());
  42. }
  43. {
  44. // Empty user-name and password should come out as no auth.
  45. auto req = performHttpRequest(
  46. server, "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\n\r\n");
  47. req->setUsernamePassword("", "");
  48. CPPUNIT_ASSERT(req->authenticate());
  49. }
  50. {
  51. // Empty user-name but set password should also come out as no auth.
  52. auto req = performHttpRequest(
  53. server, "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\n\r\n");
  54. req->setUsernamePassword("", "pass");
  55. CPPUNIT_ASSERT(req->authenticate());
  56. }
  57. {
  58. // Client provided credentials should be ignored when there is no auth.
  59. auto req = performHttpRequest(
  60. server,
  61. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNz\r\n\r\n");
  62. req->setUsernamePassword("", "pass");
  63. CPPUNIT_ASSERT(req->authenticate());
  64. }
  65. {
  66. // Correct client provided credentials should match.
  67. auto req = performHttpRequest(
  68. server,
  69. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNz\r\n\r\n");
  70. req->setUsernamePassword("user", "pass");
  71. CPPUNIT_ASSERT(req->authenticate());
  72. }
  73. {
  74. // Correct client provided credentials should match (2).
  75. // Embedded nulls
  76. auto req = performHttpRequest(
  77. server,
  78. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcgBudWxsOnBhc3MAbnVsbA==\r\n\r\n");
  79. req->setUsernamePassword(std::string("user\0null", 9), std::string("pass\0null", 9));
  80. CPPUNIT_ASSERT(req->authenticate());
  81. }
  82. {
  83. // Correct client provided credentials should match (3).
  84. // Embedded, leading nulls
  85. auto req = performHttpRequest(
  86. server,
  87. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic AHVzZXI6AHBhc3M=\r\n\r\n");
  88. req->setUsernamePassword(std::string("\0user", 5), std::string("\0pass", 5));
  89. CPPUNIT_ASSERT(req->authenticate());
  90. }
  91. {
  92. // Correct client provided credentials should match (3).
  93. // Whitespace
  94. auto req = performHttpRequest(
  95. server,
  96. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic IHVzZXIJOgpwYXNzDQ==\r\n\r\n");
  97. req->setUsernamePassword(" user\t", "\npass\r");
  98. CPPUNIT_ASSERT(req->authenticate());
  99. }
  100. {
  101. // Wrong client provided credentials should NOT match.
  102. auto req = performHttpRequest(
  103. server,
  104. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNz\r\n\r\n");
  105. req->setUsernamePassword("user", "pass2");
  106. CPPUNIT_ASSERT(!req->authenticate());
  107. }
  108. {
  109. // Wrong client provided credentials should NOT match (2).
  110. auto req = performHttpRequest(
  111. server,
  112. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNz\r\n\r\n");
  113. req->setUsernamePassword("user2", "pass");
  114. CPPUNIT_ASSERT(!req->authenticate());
  115. }
  116. {
  117. // Wrong client provided credentials should NOT match (3).
  118. // Embedded null in pass config.
  119. auto req = performHttpRequest(
  120. server,
  121. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNz\r\n\r\n");
  122. req->setUsernamePassword("user", std::string("pass\0three", 10));
  123. CPPUNIT_ASSERT(!req->authenticate());
  124. }
  125. {
  126. // Wrong client provided credentials should NOT match (4).
  127. // Embedded null in user config.
  128. auto req = performHttpRequest(
  129. server,
  130. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNz\r\n\r\n");
  131. req->setUsernamePassword(std::string("user\0four", 9), "pass");
  132. CPPUNIT_ASSERT(!req->authenticate());
  133. }
  134. {
  135. // Wrong client provided credentials should NOT match (5).
  136. // Embedded null in http auth.
  137. auto req = performHttpRequest(
  138. server,
  139. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic dXNlcjpwYXNzAHRocmVl\r\n\r\n");
  140. req->setUsernamePassword("user", "pass");
  141. CPPUNIT_ASSERT(!req->authenticate());
  142. }
  143. {
  144. // Wrong client provided credentials should NOT match (6).
  145. // Embedded null in http auth.
  146. // Embedded, leading nulls
  147. auto req = performHttpRequest(
  148. server,
  149. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\nAuthorization: Basic AHVzZXI6AHBhc3M=\r\n\r\n");
  150. req->setUsernamePassword(std::string("\0user5", 6), std::string("\0pass", 5));
  151. CPPUNIT_ASSERT(!req->authenticate());
  152. }
  153. {
  154. // When there is a user and password, the client must actually provide auth.
  155. auto req = performHttpRequest(
  156. server,
  157. "GET / HTTP/1.1\r\nUser-Agent: aria2-test\r\n\r\n");
  158. req->setUsernamePassword("user", "pass");
  159. CPPUNIT_ASSERT(!req->authenticate());
  160. }
  161. }
  162. } // namespace aria2