std::cout << "\n" << std::flush;
}
+ /*}}}*/
+ // AcqMethod::DropPrivsOrDie - Drop privileges or die /*{{{*/
+ // ---------------------------------------------------------------------
+ /* */
+ void pkgAcqMethod::DropPrivsOrDie()
+ {
+ if (!DropPrivs()) {
+ Fail(false);
+ exit(112); /* call the european emergency number */
+ }
+ }
+
/*}}}*/
// AcqMethod::URIStart - Indicate a download is starting /*{{{*/
// ---------------------------------------------------------------------
if (hash.empty() == false)
Tmp->ExpectedHashes.push_back(HashString(*t, hash));
}
+ char *End;
+ Tmp->ExpectedSize = strtoll(LookupTag(Message, "Expected-Size", "0").c_str(), &End, 10);
Tmp->Next = 0;
// Append it to the list
bool IndexFile;
bool FailIgnore;
HashStringList ExpectedHashes;
+ unsigned long long ExpectedSize;
};
struct FetchResult
pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
virtual ~pkgAcqMethod() {};
-
+ void DropPrivsOrDie();
private:
APT_HIDDEN void Dequeue();
};
#include <apt-pkg/hashes.h>
#include <apt-pkg/netrc.h>
#include <apt-pkg/strutl.h>
+ #include <apt-pkg/proxy.h>
#include <stddef.h>
#include <stdlib.h>
// CircleBuf::CircleBuf - Circular input buffer /*{{{*/
// ---------------------------------------------------------------------
/* */
-CircleBuf::CircleBuf(unsigned long long Size) : Size(Size), Hash(0)
+CircleBuf::CircleBuf(unsigned long long Size)
+ : Size(Size), Hash(0), TotalWriten(0)
{
Buf = new unsigned char[Size];
Reset();
InP = 0;
OutP = 0;
StrPos = 0;
+ TotalWriten = 0;
MaxGet = (unsigned long long)-1;
OutQueue = string();
if (Hash != 0)
return false;
}
+
+ TotalWriten += Res;
if (Hash != 0)
Hash->Add(Buf + (OutP%Size),Res);
Persistent = true;
// Determine the proxy setting
+ AutoDetectProxy(ServerName);
string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host);
if (!SpecificProxy.empty())
{
return _error->Errno("write",_("Error writing to output file"));
}
- if (ExpectedSize > 0 && In.TotalWriten > ExpectedSize)
++ if (ExpectedSize > 0 && File && File->Tell() > ExpectedSize)
++ {
+ return _error->Error("Writing more data than expected (%llu > %llu)",
- In.TotalWriten, ExpectedSize);
++ File->Tell(), ExpectedSize);
++ }
+
// Handle commands from APT
if (FD_ISSET(STDIN_FILENO,&rfds))
{
Req << "\r\n";
if (Debug == true)
- cerr << Req << endl;
+ cerr << Req.str() << endl;
Server->WriteResponse(Req.str());
}
PipelineDepth);
Debug = _config->FindB("Debug::Acquire::http",false);
- // Get the proxy to use
- AutoDetectProxy();
-
- return true;
- }
- /*}}}*/
- // HttpMethod::AutoDetectProxy - auto detect proxy /*{{{*/
- // ---------------------------------------------------------------------
- /* */
- bool HttpMethod::AutoDetectProxy()
- {
- // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
- // name without the dash ("-")
- AutoDetectProxyCmd = _config->Find("Acquire::http::Proxy-Auto-Detect",
- _config->Find("Acquire::http::ProxyAutoDetect"));
-
- if (AutoDetectProxyCmd.empty())
- return true;
-
- if (Debug)
- clog << "Using auto proxy detect command: " << AutoDetectProxyCmd << endl;
-
- int Pipes[2] = {-1,-1};
- if (pipe(Pipes) != 0)
- return _error->Errno("pipe", "Failed to create Pipe");
-
- pid_t Process = ExecFork();
- if (Process == 0)
- {
- close(Pipes[0]);
- dup2(Pipes[1],STDOUT_FILENO);
- SetCloseExec(STDOUT_FILENO,false);
-
- const char *Args[2];
- Args[0] = AutoDetectProxyCmd.c_str();
- Args[1] = 0;
- execv(Args[0],(char **)Args);
- cerr << "Failed to exec method " << Args[0] << endl;
- _exit(100);
- }
- char buf[512];
- int InFd = Pipes[0];
- close(Pipes[1]);
- int res = read(InFd, buf, sizeof(buf)-1);
- ExecWait(Process, "ProxyAutoDetect", true);
-
- if (res < 0)
- return _error->Errno("read", "Failed to read");
- if (res == 0)
- return _error->Warning("ProxyAutoDetect returned no data");
-
- // add trailing \0
- buf[res] = 0;
-
- if (Debug)
- clog << "auto detect command returned: '" << buf << "'" << endl;
-
- if (strstr(buf, "http://") == buf)
- _config->Set("Acquire::http::proxy", _strstrip(buf));
-
return true;
}
/*}}}*/
public:
Hashes *Hash;
+ // total amount of data that got written so far
+ unsigned long long TotalWriten;
// Read data in
bool Read(int Fd);
bool ReadSpace() const {return Size - (InP - OutP) > 0;};
bool WriteSpace() const {return InP - OutP > 0;};
- // Dump everything
void Reset();
+ // Dump everything
void Stats();
CircleBuf(unsigned long long Size);
public:
virtual void SendReq(FetchItem *Itm);
- /** \brief Try to AutoDetect the proxy */
- bool AutoDetectProxy();
-
virtual bool Configuration(std::string Message);
virtual ServerState * CreateServerState(URI uri);
#include <apt-pkg/configuration.h>
#include <apt-pkg/macros.h>
#include <apt-pkg/strutl.h>
+ #include <apt-pkg/proxy.h>
#include <sys/stat.h>
#include <sys/time.h>
if(me->File->Write(buffer, size*nmemb) != true)
return false;
+ me->TotalWritten += size*nmemb;
+ if(me->TotalWritten > me->Queue->ExpectedSize)
+ return _error->Error("Writing more data than expected (%llu > %llu)",
+ me->TotalWritten, me->Queue->ExpectedSize);
+
+
return size*nmemb;
}
{
URI ServerName = Queue->Uri;
+ // Determine the proxy setting
+ AutoDetectProxy(ServerName);
+
// Curl should never read proxy settings from the environment, as
// we determine which proxy to use. Do this for consistency among
// methods and prevent an environment variable overriding a
HttpsMethod Mth;
curl_global_init(CURL_GLOBAL_SSL) ;
+ Mth.DropPrivsOrDie();
+
return Mth.Run();
}
CURL *curl;
FetchResult Res;
HttpsServerState *Server;
+ unsigned long long TotalWritten;
public:
FileFd *File;
-
- HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), Server(NULL), File(NULL)
+
- HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), TotalWritten(0), File(NULL)
++ HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), Server(NULL), TotalWritten(0), File(NULL)
{
- File = 0;
curl = curl_easy_init();
};
// ---------------------------------------------------------------------
/* Returns 0 if things are OK, 1 if an IO error occurred and 2 if a header
parse error occurred */
- ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File)
+ ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File,
+ const std::string &Uri)
{
State = Header;
continue;
if (Owner->Debug == true)
- clog << Data;
+ clog << "Answer for: " << Uri << endl << Data;
for (string::const_iterator I = Data.begin(); I < Data.end(); ++I)
{
failure */
if (Server->Result < 200 || Server->Result >= 300)
{
- char err[255];
- snprintf(err,sizeof(err)-1,"HttpError%i",Server->Result);
+ std::string err;
+ strprintf(err, "HttpError%u", Server->Result);
SetFailReason(err);
- _error->Error("%u %s",Server->Result,Server->Code);
+ _error->Error("%u %s", Server->Result, Server->Code);
if (Server->HaveContent == true)
return ERROR_WITH_CONTENT_PAGE;
return ERROR_UNRECOVERABLE;
Fetch(0);
// Fetch the next URL header data from the server.
- switch (Server->RunHeaders(File))
+ switch (Server->RunHeaders(File, Queue->Uri))
{
case ServerState::RUN_HEADERS_OK:
break;
// Run the data
bool Result = true;
+
+ // ensure we don't fetch too much
+ if (Queue->ExpectedSize > 0)
+ Server->ExpectedSize = Queue->ExpectedSize;
+
if (Server->HaveContent)
Result = Server->RunData(File);
QueueBack = Queue;
}
else
++ {
++ Server->Close();
Fail(true);
++ }
}
break;
}
URI Proxy;
unsigned long TimeOut;
+ unsigned long long ExpectedSize;
+
protected:
ServerMethod *Owner;
RUN_HEADERS_PARSE_ERROR
};
/** \brief Get the headers before the data */
- RunHeadersResult RunHeaders(FileFd * const File);
+ RunHeadersResult RunHeaders(FileFd * const File, const std::string &Uri);
bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
virtual void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0;
StartPos = 0; Encoding = Closes; time(&Date); HaveContent = false;
- State = Header; Persistent = false; Pipeline = true;};
+ State = Header; Persistent = false; Pipeline = true; ExpectedSize = 0;};
virtual bool WriteResponse(std::string const &Data) = 0;
/** \brief Transfer the data from the socket */
--- /dev/null
--- /dev/null
++#!/bin/sh
++set -e
++
++TESTDIR=$(readlink -f $(dirname $0))
++. $TESTDIR/framework
++
++setupenvironment
++configarchitecture "i386"
++
++insertpackage 'unstable' 'apt' 'all' '1.0'
++
++setupaptarchive --no-update
++changetowebserver
++
++# normal update works fine
++testsuccess aptget update
++
++# append junk at the end of the Packages.gz/Packages
++SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)"
++echo "1234567890" >> aptarchive/dists/unstable/main/binary-i386/Packages.gz
++echo "1234567890" >> aptarchive/dists/unstable/main/binary-i386/Packages
++NEW_SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)"
++rm -f rootdir/var/lib/apt/lists/localhost*
++testequal "W: Failed to fetch http://localhost:8080/dists/unstable/main/binary-i386/Packages Writing more data than expected ($NEW_SIZE > $SIZE) [IP: ::1 8080]
++
++E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
++