Explorar o código

Don't send basic auth header to service operated on differenct port.

When --http-auth-challenge=true, aria2 only sends basic auth header
when requested. Old implementation sends basic auth header to service
operated in different port in successive request. This change avoid
this bug.
Tatsuhiro Tsujikawa %!s(int64=14) %!d(string=hai) anos
pai
achega
4ea28cb837

+ 24 - 18
src/AuthConfigFactory.cc

@@ -66,11 +66,14 @@ AuthConfigFactory::createAuthConfig
       if(!request->getUsername().empty()) {
         updateBasicCred(BasicCred(request->getUsername(),
                                   request->getPassword(),
-                                  request->getHost(), request->getDir(), true));
+                                  request->getHost(),
+                                  request->getPort(),
+                                  request->getDir(), true));
         return createAuthConfig(request->getUsername(), request->getPassword());
       }
       std::deque<BasicCred>::const_iterator i =
-        findBasicCred(request->getHost(), request->getDir());
+        findBasicCred(request->getHost(), request->getPort(),
+                      request->getDir());
       if(i == basicCreds_.end()) {
         return SharedHandle<AuthConfig>();
       } else {
@@ -180,10 +183,13 @@ void AuthConfigFactory::updateBasicCred(const BasicCred& basicCred)
 }
 
 bool AuthConfigFactory::activateBasicCred
-(const std::string& host, const std::string& path, const Option* op)
+(const std::string& host,
+ uint16_t port,
+ const std::string& path,
+ const Option* op)
 {
 
-  std::deque<BasicCred>::iterator i = findBasicCred(host, path);
+  std::deque<BasicCred>::iterator i = findBasicCred(host, port, path);
   if(i == basicCreds_.end()) {
     SharedHandle<AuthConfig> authConfig =
       createHttpAuthResolver(op)->resolveAuthConfig(host);
@@ -191,7 +197,7 @@ bool AuthConfigFactory::activateBasicCred
       return false;
     } else {
       BasicCred bc(authConfig->getUser(), authConfig->getPassword(),
-                   host, path, true);
+                   host, port, path, true);
       i = std::lower_bound(basicCreds_.begin(), basicCreds_.end(), bc);
       basicCreds_.insert(i, bc);
       return true;
@@ -204,10 +210,10 @@ bool AuthConfigFactory::activateBasicCred
 
 AuthConfigFactory::BasicCred::BasicCred
 (const std::string& user, const std::string& password,
- const std::string& host, const std::string& path,
+ const std::string& host, uint16_t port, const std::string& path,
  bool activated):
   user_(user), password_(password),
-  host_(host), path_(path), activated_(activated)
+  host_(host), port_(port), path_(path), activated_(activated)
 {
   if(!util::endsWith(path_, "/")) {
     path_ += "/";
@@ -226,27 +232,27 @@ bool AuthConfigFactory::BasicCred::isActivated() const
 
 bool AuthConfigFactory::BasicCred::operator==(const BasicCred& cred) const
 {
-  return host_ == cred.host_ && path_ == cred.path_;
+  return host_ == cred.host_ && port_ == cred.port_ && path_ == cred.path_;
 }
 
 bool AuthConfigFactory::BasicCred::operator<(const BasicCred& cred) const
 {
-  int c = host_.compare(cred.host_);
-  if(c == 0) {
-    return path_ > cred.path_;
-  } else {
-    return c < 0;
-  }
+  return host_ < cred.host_ ||
+    (!(cred.host_ < host_) && (port_ < cred.port_ ||
+                               (!(cred.port_ < port_) && path_ > cred.path_)));
 }
 
 std::deque<AuthConfigFactory::BasicCred>::iterator
-AuthConfigFactory::findBasicCred(const std::string& host,
-                                 const std::string& path)
+AuthConfigFactory::findBasicCred
+(const std::string& host,
+ uint16_t port,
+ const std::string& path)
 {
-  BasicCred bc("", "", host, path);
+  BasicCred bc("", "", host, port, path);
   std::deque<BasicCred>::iterator i =
     std::lower_bound(basicCreds_.begin(), basicCreds_.end(), bc);
-  for(; i != basicCreds_.end() && (*i).host_ == host; ++i) {
+  for(; i != basicCreds_.end() && (*i).host_ == host && (*i).port_ == port;
+      ++i) {
     if(util::startsWith(bc.path_, (*i).path_)) {
       return i;
     }

+ 14 - 6
src/AuthConfigFactory.h

@@ -67,11 +67,12 @@ public:
     std::string user_;
     std::string password_;
     std::string host_;
+    uint16_t port_;
     std::string path_;
     bool activated_;
 
     BasicCred(const std::string& user, const std::string& password,
-              const std::string& host, const std::string& path,
+              const std::string& host, uint16_t port, const std::string& path,
               bool activated = false);
 
     void activate();
@@ -106,12 +107,19 @@ public:
   // using this AuthConfig object with given host and path "/" and
   // returns true.
   bool activateBasicCred
-  (const std::string& host, const std::string& path, const Option* op);
-
-  // Find a BasicCred using host and path and return the iterator
-  // pointing to it. If not found, then return basicCreds_.end().
+  (const std::string& host,
+   uint16_t port,
+   const std::string& path,
+   const Option* op);
+
+  // Find a BasicCred using host, port and path and return the
+  // iterator pointing to it. If not found, then return
+  // basicCreds_.end().
   std::deque<AuthConfigFactory::BasicCred>::iterator
-  findBasicCred(const std::string& host, const std::string& path);
+  findBasicCred
+  (const std::string& host,
+   uint16_t port,
+   const std::string& path);
 
   // If the same BasicCred is already added, then it is replaced with
   // given basicCred. Otherwise, insert given basicCred to

+ 2 - 1
src/HttpSkipResponseCommand.cc

@@ -199,7 +199,8 @@ bool HttpSkipResponseCommand::processResponse()
       if(getOption()->getAsBool(PREF_HTTP_AUTH_CHALLENGE) &&
          !httpResponse_->getHttpRequest()->authenticationUsed() &&
          getDownloadEngine()->getAuthConfigFactory()->activateBasicCred
-         (getRequest()->getHost(), getRequest()->getDir(), getOption().get())) {
+         (getRequest()->getHost(), getRequest()->getPort(),
+          getRequest()->getDir(), getOption().get())) {
         return prepareForRetry(0);
       } else {
         throw DL_ABORT_EX2(EX_AUTH_FAILED,

+ 16 - 8
test/AuthConfigFactoryTest.cc

@@ -57,7 +57,7 @@ void AuthConfigFactoryTest::testCreateAuthConfig_http()
   // not activated
   CPPUNIT_ASSERT(!factory.createAuthConfig(req, &option));
 
-  CPPUNIT_ASSERT(factory.activateBasicCred("localhost", "/", &option));
+  CPPUNIT_ASSERT(factory.activateBasicCred("localhost", 80, "/", &option));
 
   CPPUNIT_ASSERT_EQUAL(std::string("localhostuser:localhostpass"),
                        factory.createAuthConfig(req, &option)->getAuthText());
@@ -65,7 +65,7 @@ void AuthConfigFactoryTest::testCreateAuthConfig_http()
   // See default token in netrc is ignored.
   req->setUri("http://mirror/");
 
-  CPPUNIT_ASSERT(!factory.activateBasicCred("mirror", "/", &option));
+  CPPUNIT_ASSERT(!factory.activateBasicCred("mirror", 80, "/", &option));
 
   CPPUNIT_ASSERT(!factory.createAuthConfig(req, &option));
 
@@ -75,7 +75,7 @@ void AuthConfigFactoryTest::testCreateAuthConfig_http()
 
   CPPUNIT_ASSERT(!factory.createAuthConfig(req, &option));
 
-  CPPUNIT_ASSERT(factory.activateBasicCred("mirror", "/", &option));
+  CPPUNIT_ASSERT(factory.activateBasicCred("mirror", 80, "/", &option));
 
   CPPUNIT_ASSERT_EQUAL(std::string("userDefinedUser:userDefinedPassword"),
                        factory.createAuthConfig(req, &option)->getAuthText());
@@ -204,20 +204,25 @@ void AuthConfigFactoryTest::testUpdateBasicCred()
   AuthConfigFactory factory;
 
   factory.updateBasicCred
-    (AuthConfigFactory::BasicCred("myname", "mypass", "localhost", "/", true));
+    (AuthConfigFactory::BasicCred("myname", "mypass", "localhost", 80, "/", true));
   factory.updateBasicCred
-    (AuthConfigFactory::BasicCred("price","j38jdc","localhost","/download", true));
+    (AuthConfigFactory::BasicCred("price", "j38jdc", "localhost", 80, "/download", true));
   factory.updateBasicCred
-    (AuthConfigFactory::BasicCred("alice","ium8","localhost","/documents", true));
+    (AuthConfigFactory::BasicCred("soap", "planB", "localhost", 80, "/download/beta", true));
   factory.updateBasicCred
-    (AuthConfigFactory::BasicCred("jack", "jackx","mirror", "/doc", true));
+    (AuthConfigFactory::BasicCred("alice", "ium8", "localhost", 80, "/documents", true));
+  factory.updateBasicCred
+    (AuthConfigFactory::BasicCred("jack", "jackx", "mirror", 80, "/doc", true));
 
   SharedHandle<Request> req(new Request());
   req->setUri("http://localhost/download/v2.6/Changelog");
-  
   CPPUNIT_ASSERT_EQUAL(std::string("price:j38jdc"),
                        factory.createAuthConfig(req, &option)->getAuthText());
 
+  req->setUri("http://localhost/download/beta/v2.7/Changelog");
+  CPPUNIT_ASSERT_EQUAL(std::string("soap:planB"),
+                       factory.createAuthConfig(req, &option)->getAuthText());
+
   req->setUri("http://localhost/documents/reference.html");
   CPPUNIT_ASSERT_EQUAL(std::string("alice:ium8"),
                        factory.createAuthConfig(req, &option)->getAuthText());
@@ -230,6 +235,9 @@ void AuthConfigFactoryTest::testUpdateBasicCred()
   CPPUNIT_ASSERT_EQUAL(std::string("myname:mypass"),
                        factory.createAuthConfig(req, &option)->getAuthText());
 
+  req->setUri("http://localhost:8080/doc/readme.txt");
+  CPPUNIT_ASSERT(!factory.createAuthConfig(req, &option));
+
   req->setUri("http://local/");
   CPPUNIT_ASSERT(!factory.createAuthConfig(req, &option));
 

+ 1 - 1
test/HttpRequestTest.cc

@@ -244,7 +244,7 @@ void HttpRequestTest::testCreateRequest()
   option_->put(PREF_HTTP_PASSWD, "aria2passwd");
 
   CPPUNIT_ASSERT(authConfigFactory_->activateBasicCred
-                 ("localhost", "/", option_.get()));
+                 ("localhost", 8080, "/", option_.get()));
 
   expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n"
     "User-Agent: aria2\r\n"