[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#212732: marked as done (support redirects and interactive authentication (Progeny))



Your message dated Wed, 13 Jan 2016 01:04:47 +0100
with message-id <20160113010341.GA5693@debian.org>
and subject line Re: Bug#212732: Bug#427909: Bug#212732: support redirects and interactive authentication (Progeny)
has caused the Debian Bug report #212732,
regarding support redirects and interactive authentication (Progeny)
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
212732: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=212732
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: apt
Version: 0.5.9
Severity: wishlist
Tags: patch

The patch below adds interactive authentication and redirect support to
apt's http method.

There are changes to apt-pkg in this patch:

 - New acquire method messages: 103 Redirect and 404 Authenticate from
the method, and 604 Authenticated to the method.

 - New acquire status method: Authenticate.  Called by apt when
authentication is needed.  The default implementation simply returns
false, which triggers apt's old behavior when asked to authenticate.

There is also an Authenticate implementation for acqprogress, which
enables interactive authentication for apt-get.

To my knowledge, all apt frontends should build without problems with
these changes.

Index: methods/http.cc
===================================================================
--- methods/http.cc (.../tags/apt-debian-0.5.9)	(revision 37)
+++ methods/http.cc
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -40,6 +40,7 @@
 #include <errno.h>
 #include <string.h>
 #include <iostream>
+#include <map>
 
 // Internet stuff
 #include <netdb.h>
@@ -56,6 +57,7 @@
 time_t HttpMethod::FailTime = 0;
 unsigned long PipelineDepth = 10;
 unsigned long TimeOut = 120;
+bool ChokePipe = true;
 bool Debug = false;
 
 // CircleBuf::CircleBuf - Circular input buffer				/*{{{*/
@@ -591,6 +593,31 @@
       return true;
    }
 
+   if (stringcasecmp(Tag,"Location:") == 0)
+   {
+      Location = Val;
+      return true;
+   }
+
+   if (stringcasecmp(Tag,"WWW-Authenticate:") == 0 ||
+       stringcasecmp(Tag,"Proxy-Authenticate:") == 0)
+   {
+      string::size_type SplitPoint = Val.find(' ');
+      string AuthType = Val.substr(0, SplitPoint);
+      string RealmStr = Val.substr(SplitPoint + 1, 
+				   Val.length() - SplitPoint - 1);
+      SplitPoint = RealmStr.find('=');
+      string FoundRealm = RealmStr.substr(SplitPoint, 
+					  RealmStr.length() - SplitPoint);
+
+      if (stringcasecmp(Tag,"WWW-Authenticate:") == 0)
+	 Realm = FoundRealm;
+      else
+	 ProxyRealm = FoundRealm;
+
+      return true;
+   }
+
    return true;
 }
 									/*}}}*/
@@ -853,7 +880,8 @@
      1 - IMS hit
      3 - Unrecoverable error 
      4 - Error with error content page
-     5 - Unrecoverable non-server error (close the connection) */
+     5 - Unrecoverable non-server error (close the connection)
+     6 - Try again with a new or changed URI  */
 int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
 {
    // Not Modified
@@ -864,7 +892,96 @@
       Res.LastModified = Queue->LastModified;
       return 1;
    }
-   
+
+   /* Redirect
+    *
+    * Note that it is only OK for us to treat all redirection the same
+    * because we *always* use GET, not other HTTP methods.  There are
+    * three redirection codes for which it is not appropriate that we
+    * redirect.  Pass on those codes so the error handling kicks in.
+    */
+   if ((Srv->Result > 300 && Srv->Result < 400)
+       && (Srv->Result != 300       // Multiple Choices
+           && Srv->Result != 304    // Not Modified
+           && Srv->Result != 306))  // (Not part of HTTP/1.1, reserved)
+   {
+      if (!Srv->Location.empty())
+      {
+         NextURI = Srv->Location;
+         return 6;
+      }
+      else
+	 return 3;
+   }
+
+   // Authentication
+   if (Srv->Result == 401)
+   {
+      string Description;
+      string AuthUser, AuthPass;
+      vector<AuthRec>::iterator CurrentAuth;
+      URI ParsedURI(Queue->Uri);
+
+      // Have we had to log in to this site before?
+      if (ParsedURI.User.empty())
+      {
+	 for (CurrentAuth = AuthList.begin(); CurrentAuth != AuthList.end();
+	      CurrentAuth++)
+	    if (CurrentAuth->Host == Srv->ServerName.Host &&
+		CurrentAuth->Realm == Srv->Realm)
+	    {
+	       AuthUser = CurrentAuth->User;
+	       AuthPass = CurrentAuth->Password;
+	       break;
+	    }
+      }
+      else
+	 CurrentAuth = AuthList.end();
+
+      // Nope - get username and password
+      if (CurrentAuth == AuthList.end())
+      {
+	 Description = ParsedURI.Host + ":" + Srv->Realm;
+
+#ifdef WITH_SSL
+	 if (ParsedURI.Access == "https")
+	    Description += string(" (secure)");
+#endif
+
+	 if (NeedAuth(Description, AuthUser, AuthPass) == true)
+	 {
+	    // Got new credentials; save them
+	    AuthRec NewAuthInfo;
+
+	    NewAuthInfo.Host = Srv->ServerName.Host;
+	    NewAuthInfo.Realm = Srv->Realm;
+	    NewAuthInfo.User = AuthUser;
+	    NewAuthInfo.Password = AuthPass;
+
+	    for (CurrentAuth = AuthList.begin(); CurrentAuth !=
AuthList.end();
+		 CurrentAuth++)
+	       if (CurrentAuth->Host == Srv->ServerName.Host &&
+		   CurrentAuth->Realm == Srv->Realm)
+	       {
+		  *CurrentAuth = NewAuthInfo;
+		  break;
+	       }
+	    
+	    if (CurrentAuth == AuthList.end())
+	       AuthList.push_back(NewAuthInfo);
+	 }
+	 else
+	    // Interactive auth failed
+	    return 4;
+      }
+
+      // Try the same URI again, with credentials this time
+      ParsedURI.User = AuthUser;
+      ParsedURI.Password = AuthPass;
+      NextURI = ParsedURI;
+      return 6;
+   }
+
    /* We have a reply we dont handle. This should indicate a perm
server
       failure */
    if (Srv->Result < 200 || Srv->Result >= 300)
@@ -956,10 +1073,21 @@
       // If pipelining is disabled, we only queue 1 request
       if (Server->Pipeline == false && Depth >= 0)
 	 break;
+
+      // If we're choking the pipeline, we only queue 1 request
+      if (ChokePipe == true && Depth >= 0)
+      {
+	 ChokePipe = false;
+	 break;
+      }
       
       // Make sure we stick with the same server
       if (Server->Comp(I->Uri) == false)
+      {
+	 ChokePipe = true;
 	 break;
+      }
+
       if (QueueBack == I)
 	 Tail = true;
       if (Tail == true)
@@ -994,12 +1122,17 @@
 /* */
 int HttpMethod::Loop()
 {
+   typedef vector<string> StringVector;
+   typedef vector<string>::iterator StringVectorIterator;
+   map<string, StringVector> Redirected;
+
    signal(SIGTERM,SigTerm);
    signal(SIGINT,SigTerm);
    
    Server = 0;
    
    int FailCounter = 0;
+
    while (1)
    {      
       // We have no commands, wait for some to arrive
@@ -1164,6 +1297,46 @@
 	    File = 0;
 	    break;
 	 }
+
+	 // Try again with a new URL
+	 case 6:
+	 {
+	    // Clear rest of response if there is content
+	    if (Server->HaveContent)
+	    {
+	       File = new FileFd("/dev/null",FileFd::WriteExists);
+	       Server->RunData();
+	       delete File;
+	       File = 0;
+	    }
+
+	    /* Detect redirect loops.  No more redirects are allowed
+	       after the same URI is seen twice in a queue item. */
+	    StringVector &R = Redirected[Queue->DestFile];
+	    bool StopRedirects = false;
+	    if (R.size() == 0)
+	       R.push_back(Queue->Uri);
+	    else if (R[0] == "STOP")
+	       StopRedirects = true;
+	    else
+	    {
+	       for (StringVectorIterator I = R.begin();	I != R.end(); I++)
+		  if (Queue->Uri == *I)
+		  {
+		     R[0] = "STOP";
+		     break;
+		  }
+
+	       R.push_back(Queue->Uri);
+	    }
+
+	    if (StopRedirects == false)
+	       Redirect(NextURI);
+	    else
+	       Fail();
+
+	    break;
+	 }
 	 
 	 default:
 	 Fail(_("Internal error"));
Index: methods/http.h
===================================================================
--- methods/http.h (.../tags/apt-debian-0.5.9)	(revision 37)
+++ methods/http.h (.../branches/apt-resolve-0.5.9-redir-auth)	(revision
37)
@@ -94,6 +94,8 @@
    enum {Chunked,Stream,Closes} Encoding;
    enum {Header, Data} State;
    bool Persistent;
+   string Location;
+   string Realm, ProxyRealm;
    
    // This is a Persistent attribute of the server itself.
    bool Pipeline;
@@ -123,6 +125,14 @@
 
 class HttpMethod : public pkgAcqMethod
 {
+   struct AuthRec
+   {
+      string Host;
+      string Realm;
+      string User;
+      string Password;
+   };
+
    void SendReq(FetchItem *Itm,CircleBuf &Out);
    bool Go(bool ToFile,ServerState *Srv);
    bool Flush(ServerState *Srv);
@@ -137,6 +147,9 @@
    static int FailFd;
    static time_t FailTime;
    static void SigTerm(int);
+
+   string NextURI;
+   vector<AuthRec> AuthList;
    
    public:
    friend class ServerState;
Index: apt-pkg/acquire.h
===================================================================
--- apt-pkg/acquire.h (.../tags/apt-debian-0.5.9)	(revision 37)
+++ apt-pkg/acquire.h
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -267,6 +267,9 @@
    
    // Called to change media
    virtual bool MediaChange(string Media,string Drive) = 0;
+
+   // Called to authenticate
+   virtual bool Authenticate(string Desc,string &User,string &Pass);
    
    // Each of these is called by the workers when an event occures
    virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {};
Index: apt-pkg/acquire-worker.h
===================================================================
--- apt-pkg/acquire-worker.h (.../tags/apt-debian-0.5.9)	(revision 37)
+++ apt-pkg/acquire-worker.h
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -62,6 +62,7 @@
    bool Capabilities(string Message);
    bool SendConfiguration();
    bool MediaChange(string Message);
+   bool Authenticate(string Message);
    
    bool MethodFailure();
    void ItemDone();
Index: apt-pkg/acquire-worker.cc
===================================================================
--- apt-pkg/acquire-worker.cc (.../tags/apt-debian-0.5.9)	(revision 37)
+++ apt-pkg/acquire-worker.cc
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -221,6 +221,20 @@
 	 case 102:
 	 Status = LookupTag(Message,"Message");
 	 break;
+
+	 // 103 Redirect
+	 case 103:
+	 {
+	    if (Itm == 0)
+	    {
+	       _error->Error("Method gave invalid 103 Redirect message");
+	       break;
+	    }
+
+	    string NewURI = LookupTag(Message,"New-URI",URI.c_str());
+	    Itm->URI = NewURI;
+	    break;
+	 }
 	    
 	 // 200 URI Start
 	 case 200:
@@ -324,6 +338,11 @@
 	 case 403:
 	 MediaChange(Message); 
 	 break;
+
+	 // 404 Authenticate
+	 case 404:
+	 Authenticate(Message);
+	 break;
       }      
    }
    return true;
@@ -388,6 +407,34 @@
    return true;
 }
 									/*}}}*/
+// Worker::Authenticate - Request authentication       			/*{{{*/
+//
---------------------------------------------------------------------
+/* */
+bool pkgAcquire::Worker::Authenticate(string Message)
+{
+   string User, Pass;
+   if (Log == 0 || Log->Authenticate(LookupTag(Message,"Description"),
+				     User,Pass) == false)
+   {
+      char S[300];
+      snprintf(S,sizeof(S),"604 Authenticated\nFailed: true\n\n");
+      if (Debug == true)
+	 clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl;
+      OutQueue += S;
+      OutReady = true;
+      return true;
+   }
+
+   char S[300];
+   snprintf(S,sizeof(S),"604 Authenticated\nUser: %s\nPassword:
%s\n\n",
+	    User.c_str(), Pass.c_str());
+   if (Debug == true)
+      clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl;
+   OutQueue += S;
+   OutReady = true;
+   return true;
+}
+									/*}}}*/
 // Worker::SendConfiguration - Send the config to the method		/*{{{*/
 //
---------------------------------------------------------------------
 /* */
Index: apt-pkg/acquire-method.cc
===================================================================
--- apt-pkg/acquire-method.cc (.../tags/apt-debian-0.5.9)	(revision 37)
+++ apt-pkg/acquire-method.cc
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -26,6 +26,7 @@
 #include <apt-pkg/hashes.h>
 
 #include <iostream>
+#include <sstream>
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -133,24 +134,22 @@
 {
    if (Queue == 0)
       abort();
-   
-   char S[1024] = "";
-   char *End = S;
-   
-   End += snprintf(S,sizeof(S),"200 URI Start\nURI:
%s\n",Queue->Uri.c_str());
+
+   ostringstream s;
+
+   s << "200 URI Start\nURI: " << Queue->Uri << "\n";
    if (Res.Size != 0)
-      End += snprintf(End,sizeof(S)-4 - (End - S),"Size:
%lu\n",Res.Size);
-   
+      s << "Size: " << Res.Size << "\n";
+
    if (Res.LastModified != 0)
-      End += snprintf(End,sizeof(S)-4 - (End - S),"Last-Modified:
%s\n",
-		      TimeRFC1123(Res.LastModified).c_str());
-   
+      s << "Last-Modified: " << TimeRFC1123(Res.LastModified) << "\n";
+
    if (Res.ResumePoint != 0)
-      End += snprintf(End,sizeof(S)-4 - (End - S),"Resume-Point:
%lu\n",
-		      Res.ResumePoint);
-      
-   strcat(End,"\n");
-   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+      s << "Resume-Point: " << Res.ResumePoint << "\n";
+
+   s << "\n";
+   string S = s.str();
+   if (write(STDOUT_FILENO,S.c_str(),S.size()) != (ssize_t)S.size())
       exit(100);
 }
 									/*}}}*/
@@ -161,60 +160,54 @@
 {
    if (Queue == 0)
       abort();
-   
-   char S[1024] = "";
-   char *End = S;
-   
-   End += snprintf(S,sizeof(S),"201 URI Done\nURI:
%s\n",Queue->Uri.c_str());
 
+   ostringstream s;
+
+   s << "201 URI Done\nURI: " << Queue->Uri << "\n";
+
    if (Res.Filename.empty() == false)
-      End += snprintf(End,sizeof(S)-50 - (End - S),"Filename:
%s\n",Res.Filename.c_str());
-   
+      s << "Filename: " << Res.Filename << "\n";
+
    if (Res.Size != 0)
-      End += snprintf(End,sizeof(S)-50 - (End - S),"Size:
%lu\n",Res.Size);
-   
+      s << "Size: " << Res.Size << "\n";
+
    if (Res.LastModified != 0)
-      End += snprintf(End,sizeof(S)-50 - (End - S),"Last-Modified:
%s\n",
-		      TimeRFC1123(Res.LastModified).c_str());
+      s << "Last-Modified: " << TimeRFC1123(Res.LastModified) << "\n";
 
    if (Res.MD5Sum.empty() == false)
-      End += snprintf(End,sizeof(S)-50 - (End - S),"MD5-Hash:
%s\n",Res.MD5Sum.c_str());
+      s << "MD5-Hash: " << Res.MD5Sum << "\n";
    if (Res.SHA1Sum.empty() == false)
-      End += snprintf(End,sizeof(S)-50 - (End - S),"SHA1-Hash:
%s\n",Res.SHA1Sum.c_str());
+      s << "SHA1-Hash: " << Res.SHA1Sum << "\n";
 
    if (Res.ResumePoint != 0)
-      End += snprintf(End,sizeof(S)-50 - (End - S),"Resume-Point:
%lu\n",
-		      Res.ResumePoint);
+      s << "Resume-Point: " << Res.ResumePoint << "\n";
 
    if (Res.IMSHit == true)
-      strcat(End,"IMS-Hit: true\n");
-   End = S + strlen(S);
-   
+      s << "IMS-Hit: true\n";
+
    if (Alt != 0)
    {
       if (Alt->Filename.empty() == false)
-	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-Filename:
%s\n",Alt->Filename.c_str());
+	 s << "Alt-Filename: " << Alt->Filename << "\n";
       
       if (Alt->Size != 0)
-	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-Size:
%lu\n",Alt->Size);
+	 s << "Alt-Size: " << Alt->Size << "\n";
       
       if (Alt->LastModified != 0)
-	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-Last-Modified:
%s\n",
-			 TimeRFC1123(Alt->LastModified).c_str());
+	 s << "Alt-Last-Modified: " << TimeRFC1123(Alt->LastModified) << "\n";
       
       if (Alt->MD5Sum.empty() == false)
-	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-MD5-Hash: %s\n",
-			 Alt->MD5Sum.c_str());
+	 s << "Alt-MD5-Hash: " << Alt->MD5Sum << "\n";
       if (Alt->SHA1Sum.empty() == false)
-	 End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-SHA1-Hash: %s\n",
-			 Alt->SHA1Sum.c_str());
+	 s << "Alt-SHA1-Hash: " << Alt->SHA1Sum << "\n";
       
       if (Alt->IMSHit == true)
-	 strcat(End,"Alt-IMS-Hit: true\n");
+	 s << "Alt-IMS-Hit: true\n";
    }
-   
-   strcat(End,"\n");
-   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+
+   s << "\n";
+   string S = s.str();
+   if (write(STDOUT_FILENO,S.c_str(),S.size()) != (ssize_t)S.size())
       exit(100);
 
    // Dequeue
@@ -278,6 +271,66 @@
    }   
 }
 									/*}}}*/
+// AcqMethod::NeedAuth - Request authentication				/*{{{*/
+//
---------------------------------------------------------------------
+/* This sends a 404 Authenticate message to the APT and waits for it
+   to be ackd */
+bool pkgAcqMethod::NeedAuth(string Description,string &User,string
&Pass)
+{
+   char S[1024];
+   snprintf(S,sizeof(S),"404 Authenticate\nDescription: %s\n\n",
+	    Description.c_str());
+
+   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+      exit(100);
+   
+   vector<string> MyMessages;
+   
+   /* Here we read messages until we find a 604, each non 604 message
is
+      appended to the main message list for later processing */
+   while (1)
+   {
+      if (WaitFd(STDIN_FILENO) == false)
+	 return false;
+      
+      if (ReadMessages(STDIN_FILENO,MyMessages) == false)
+	 return false;
+
+      string Message = MyMessages.front();
+      MyMessages.erase(MyMessages.begin());
+      
+      // Fetch the message number
+      char *End;
+      int Number = strtol(Message.c_str(),&End,10);
+      if (End == Message.c_str())
+      {	 
+	 cerr << "Malformed message!" << endl;
+	 exit(100);
+      }
+
+      // Change ack
+      if (Number == 604)
+      {
+	 while (MyMessages.empty() == false)
+	 {
+	    Messages.push_back(MyMessages.front());
+	    MyMessages.erase(MyMessages.begin());
+	 }
+
+	 if (StringToBool(LookupTag(Message,"Fail"),false) == false)
+	 {
+	    User = LookupTag(Message,"User");
+	    Pass = LookupTag(Message,"Password");
+	    return true;
+	 }
+	 else
+	    return false;
+      }
+      
+      Messages.push_back(Message);
+   }   
+}
+									/*}}}*/
 // AcqMethod::Configuration - Handle the configuration message		/*{{{*/
 //
---------------------------------------------------------------------
 /* This parses each configuration entry and puts it into the _config 
@@ -423,19 +476,52 @@
    va_list args;
    va_start(args,Format);
 
+   ostringstream s;
+   s << "102 Status\nURI: " << CurrentURI << "\nMessage: ";
+
    // sprintf the description
-   char S[1024];
-   unsigned int Len = snprintf(S,sizeof(S)-4,"102 Status\nURI: %s\n"
-			       "Message: ",CurrentURI.c_str());
+   char Buf[1024];
+   vsnprintf(Buf,sizeof(Buf)-4,Format,args);
+   s << Buf << "\n\n";
 
-   vsnprintf(S+Len,sizeof(S)-4-Len,Format,args);
-   strcat(S,"\n\n");
-   
-   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+   string S = s.str();
+   if (write(STDOUT_FILENO,S.c_str(),S.size()) != (ssize_t)S.size())
       exit(100);
 }
 									/*}}}*/
+// AcqMethod::Redirect - Send a redirect message			/*{{{*/
+//
---------------------------------------------------------------------
+/* This method sends the redirect message and also manipulates the
queue
+   to keep the pipeline synchronized. */
+void pkgAcqMethod::Redirect(const string &NewURI)
+{
+   string CurrentURI = "<UNKNOWN>";
+   if (Queue != 0)
+      CurrentURI = Queue->Uri;
 
+   ostringstream s;
+   s << "103 Redirect\nURI: " << CurrentURI << "\nNew-URI: " << NewURI 
+     << "\n\n";
+
+   string S = s.str();
+   if (write(STDOUT_FILENO,S.c_str(),S.size()) != (ssize_t)S.size())
+      exit(100);
+
+   // Change the URI for the request.
+   Queue->Uri = NewURI;
+
+   /* To keep the pipeline synchronized, move the current request to
+      the end of the queue, past the end of the current pipeline. */
+   FetchItem *I;
+   for (I = Queue; I->Next != 0; I = I->Next) ;
+   I->Next = Queue;
+   Queue = Queue->Next;
+   I->Next->Next = 0;
+   if (QueueBack == 0)
+      QueueBack = I->Next;
+}
+									/*}}}*/
+
 // AcqMethod::FetchResult::FetchResult - Constructor			/*{{{*/
 //
---------------------------------------------------------------------
 /* */
Index: apt-pkg/acquire-method.h
===================================================================
--- apt-pkg/acquire-method.h (.../tags/apt-debian-0.5.9)	(revision 37)
+++ apt-pkg/acquire-method.h
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -66,6 +66,7 @@
    void URIStart(FetchResult &Res);
    void URIDone(FetchResult &Res,FetchResult *Alt = 0);
    bool MediaFail(string Required,string Drive);
+   bool NeedAuth(string Description,string &User,string &Pass);
    virtual void Exit() {};
 
    public:
@@ -77,7 +78,8 @@
 
    void Log(const char *Format,...);
    void Status(const char *Format,...);
-   
+   void Redirect(const string &NewURI);
+
    int Run(bool Single = false);
    inline void SetFailExtraMsg(string Msg) {FailExtra = Msg;};
    
Index: apt-pkg/acquire.cc
===================================================================
--- apt-pkg/acquire.cc (.../tags/apt-debian-0.5.9)	(revision 37)
+++ apt-pkg/acquire.cc
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -848,3 +848,13 @@
    FetchedBytes += Size - Resume;
 }
 									/*}}}*/
+// AcquireStatus::Authenticate - Called to authenticate			/*{{{*/
+//
---------------------------------------------------------------------
+/* This is used to fetch a username and password from the user */
+bool pkgAcquireStatus::Authenticate(string Desc,string &User,string
&Pass)
+{
+   /* The default behavior for all clients is to refuse to authenticate
+      interactively; this preserves backwards compatibility. */
+   return false;
+}
+									/*}}}*/
Index: cmdline/acqprogress.h
===================================================================
--- cmdline/acqprogress.h (.../tags/apt-debian-0.5.9)	(revision 37)
+++ cmdline/acqprogress.h
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -22,6 +22,7 @@
    public:
    
    virtual bool MediaChange(string Media,string Drive);
+   virtual bool Authenticate(string Desc,string &User,string &Pass);
    virtual void IMSHit(pkgAcquire::ItemDesc &Itm);
    virtual void Fetch(pkgAcquire::ItemDesc &Itm);
    virtual void Done(pkgAcquire::ItemDesc &Itm);
Index: cmdline/acqprogress.cc
===================================================================
--- cmdline/acqprogress.cc (.../tags/apt-debian-0.5.9)	(revision 37)
+++ cmdline/acqprogress.cc
(.../branches/apt-resolve-0.5.9-redir-auth)	(revision 37)
@@ -18,6 +18,8 @@
     
 #include <stdio.h>
 #include <signal.h>
+#include <termios.h>
+#include <unistd.h>
 #include <iostream>
 									/*}}}*/
 
@@ -281,3 +283,59 @@
    return true;
 }
 									/*}}}*/
+// AcqTextStatus::Authenticate - Authenticate the user			/*{{{*/
+//
---------------------------------------------------------------------
+/* Prompt for a username and password */
+bool AcqTextStatus::Authenticate(string Desc,string &User,string &Pass)
+{
+   if (Quiet > 0)
+      return false;
+
+   cout << '\r' << BlankLine << '\r';
+
+   ioprintf(cout,_("Please login to %s\nUsername: "), Desc.c_str());
+   cout << flush;
+
+   char S[1024];
+   char C = 0;
+   size_t idx = 0;
+   while (C != '\n' && C != '\r' && idx < (sizeof(S) - 1))
+   {
+      read(STDIN_FILENO,&C,1);
+      S[idx++] = C;
+   }
+   S[--idx] = '\0';
+   User = S;
+
+   ioprintf(cout,_("Password: "));
+   cout << flush;
+
+   // Turn off echo for entering the password
+   struct termios TermIO;
+   tcgetattr(STDIN_FILENO, &TermIO);
+
+   struct termios TermIO_noecho;
+   TermIO_noecho = TermIO;
+   TermIO_noecho.c_lflag &= !ECHO;
+   tcsetattr(STDIN_FILENO, TCSANOW, &TermIO_noecho);
+
+   C = 0;
+   idx = 0;
+   while (C != '\n' && C != '\r' && idx < (sizeof(S) - 1))
+   {
+      read(STDIN_FILENO,&C,1);
+      S[idx++] = C;
+   }
+   S[--idx] = '\0';
+   Pass = S;
+
+   // Turn echo back on
+   tcsetattr(STDIN_FILENO, TCSANOW, &TermIO);
+
+   ioprintf(cout,_("\n"));
+   cout << flush;
+   
+   Update = true;
+   return true;
+}
+									/*}}}*/



--- End Message ---
--- Begin Message ---
Version: 0.7.21

Closing this bug. As documented below, redirects are supported
since some time, and interactive auth is tracked in #414204.

On Wed, Nov 11, 2009 at 11:27:27PM +0100, Simon Paillard wrote:
> On Sat, Jan 31, 2009 at 11:01:46AM +1000, Anthony Towns wrote:
> > On Fri, Jan 30, 2009 at 09:14:54PM +0100, Michael Vogt wrote:
> > > On Sun, Dec 21, 2008 at 10:45:13PM +1000, Anthony Towns wrote:
> > > > Attached is a patch against apt 0.7.19 (current in lenny/sid)
> > > > including just the Redirect support from Jeff Licquia's patch in
> > > > Bug#212732. 
> > > Thanks a lot for this, I merged it into my bzr tree and it will be
> > > part of the next merge into debian (experimental initially). 
> > 
> > Great!
> 
> Great too !
> This is in apt since 0.7.21 (but bug closure missing in debian/changelog)
> 
> I tested it successfully using 302 redirects.
> 
> Could you retroactively close this bug through the changelog ?
> 
> apt (0.7.21) unstable; urgency=low
> [...]
>   [ Michael Vogt ]
> [...]
>   * [ABI break] merge support for http redirects, thanks to
>     Jeff Licquia and Anthony Towns
> [...]
>   * methods/https.cc:
>     - add Acquire::https::AllowRedirect support
> 
>  -- Michael Vogt    Tue, 14 Apr 2009 14:12:51 +0200
> 
> 
> -- 
> Simon Paillard
> 
> 

-- 
Julian Andres Klode  - Debian Developer, Ubuntu Member

See http://wiki.debian.org/JulianAndresKlode and http://jak-linux.org/.

When replying, only quote what is necessary, and write each reply
directly below the part(s) it pertains to (`inline'). Thank you.

--- End Message ---

Reply to: