Browse Source

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 14 years ago
parent
commit
4ea28cb837

+ 24 - 18
src/AuthConfigFactory.cc

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

+ 14 - 6
src/AuthConfigFactory.h

@@ -67,11 +67,12 @@ public:
     std::string user_;
     std::string user_;
     std::string password_;
     std::string password_;
     std::string host_;
     std::string host_;
+    uint16_t port_;
     std::string path_;
     std::string path_;
     bool activated_;
     bool activated_;
 
 
     BasicCred(const std::string& user, const std::string& password,
     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);
               bool activated = false);
 
 
     void activate();
     void activate();
@@ -106,12 +107,19 @@ public:
   // using this AuthConfig object with given host and path "/" and
   // using this AuthConfig object with given host and path "/" and
   // returns true.
   // returns true.
   bool activateBasicCred
   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
   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
   // If the same BasicCred is already added, then it is replaced with
   // given basicCred. Otherwise, insert given basicCred to
   // 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) &&
       if(getOption()->getAsBool(PREF_HTTP_AUTH_CHALLENGE) &&
          !httpResponse_->getHttpRequest()->authenticationUsed() &&
          !httpResponse_->getHttpRequest()->authenticationUsed() &&
          getDownloadEngine()->getAuthConfigFactory()->activateBasicCred
          getDownloadEngine()->getAuthConfigFactory()->activateBasicCred
-         (getRequest()->getHost(), getRequest()->getDir(), getOption().get())) {
+         (getRequest()->getHost(), getRequest()->getPort(),
+          getRequest()->getDir(), getOption().get())) {
         return prepareForRetry(0);
         return prepareForRetry(0);
       } else {
       } else {
         throw DL_ABORT_EX2(EX_AUTH_FAILED,
         throw DL_ABORT_EX2(EX_AUTH_FAILED,

+ 16 - 8
test/AuthConfigFactoryTest.cc

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

+ 1 - 1
test/HttpRequestTest.cc

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