summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/configuration.cc34
-rw-r--r--apt-pkg/contrib/fileutl.cc43
-rw-r--r--apt-pkg/contrib/fileutl.h23
-rw-r--r--apt-pkg/contrib/netrc.cc296
-rw-r--r--apt-pkg/contrib/netrc.h7
5 files changed, 188 insertions, 215 deletions
diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 442e31dff..eb873bdba 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -840,9 +840,9 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
unsigned const &Depth)
{
// Open the stream for reading
- ifstream F(FName.c_str(),ios::in);
- if (F.fail() == true)
- return _error->Errno("ifstream::ifstream",_("Opening configuration file %s"),FName.c_str());
+ FileFd F;
+ if (OpenConfigurationFileFd(FName, F) == false)
+ return false;
string LineBuffer;
std::stack<std::string> Stack;
@@ -852,26 +852,15 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
int CurLine = 0;
bool InComment = false;
- while (F.eof() == false)
+ while (F.Eof() == false)
{
// The raw input line.
std::string Input;
+ if (F.ReadLine(Input) == false)
+ Input.clear();
// The input line with comments stripped.
std::string Fragment;
- // Grab the next line of F and place it in Input.
- do
- {
- char *Buffer = new char[1024];
-
- F.clear();
- F.getline(Buffer,sizeof(Buffer) / 2);
-
- Input += Buffer;
- delete[] Buffer;
- }
- while (F.fail() && !F.eof());
-
// Expand tabs in the input line and remove leading and trailing
// whitespace.
{
@@ -1161,13 +1150,10 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
bool ReadConfigDir(Configuration &Conf,const string &Dir,
bool const &AsSectional, unsigned const &Depth)
{
- vector<string> const List = GetListOfFilesInDir(Dir, "conf", true, true);
-
- // Read the files
- for (vector<string>::const_iterator I = List.begin(); I != List.end(); ++I)
- if (ReadConfigFile(Conf,*I,AsSectional,Depth) == false)
- return false;
- return true;
+ bool good = true;
+ for (auto const &I : GetListOfFilesInDir(Dir, "conf", true, true))
+ good = ReadConfigFile(Conf, I, AsSectional, Depth) && good;
+ return good;
}
/*}}}*/
// MatchAgainstConfig Constructor /*{{{*/
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index 630a98ce4..33f4f7e09 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -402,7 +402,10 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
DIR *D = opendir(Dir.c_str());
if (D == 0)
{
- _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
+ if (errno == EACCES)
+ _error->WarningE("opendir", _("Unable to read %s"), Dir.c_str());
+ else
+ _error->Errno("opendir", _("Unable to read %s"), Dir.c_str());
return List;
}
@@ -2493,9 +2496,6 @@ bool FileFd::Read(int const Fd, void *To, unsigned long long Size, unsigned long
}
/*}}}*/
// FileFd::ReadLine - Read a complete line from the file /*{{{*/
-// ---------------------------------------------------------------------
-/* Beware: This method can be quite slow for big buffers on UNcompressed
- files because of the naive implementation! */
char* FileFd::ReadLine(char *To, unsigned long long const Size)
{
*To = '\0';
@@ -2503,6 +2503,29 @@ char* FileFd::ReadLine(char *To, unsigned long long const Size)
return nullptr;
return d->InternalReadLine(To, Size);
}
+bool FileFd::ReadLine(std::string &To)
+{
+ To.clear();
+ if (d == nullptr || Failed())
+ return false;
+ constexpr size_t buflen = 4096;
+ char buffer[buflen];
+ size_t len;
+ do
+ {
+ if (d->InternalReadLine(buffer, buflen) == nullptr)
+ return false;
+ len = strlen(buffer);
+ To.append(buffer, len);
+ } while (len == buflen - 1 && buffer[len - 2] != '\n');
+ // remove the newline at the end
+ auto const i = To.find_last_not_of("\r\n");
+ if (i == std::string::npos)
+ To.clear();
+ else
+ To.erase(i + 1);
+ return true;
+}
/*}}}*/
// FileFd::Flush - Flush the file /*{{{*/
bool FileFd::Flush()
@@ -3104,3 +3127,15 @@ bool DropPrivileges() /*{{{*/
return true;
}
/*}}}*/
+bool OpenConfigurationFileFd(std::string const &File, FileFd &Fd) /*{{{*/
+{
+ int const fd = open(File.c_str(), O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ if (fd == -1)
+ return _error->WarningE("open", _("Unable to read %s"), File.c_str());
+ APT::Configuration::Compressor none(".", "", "", nullptr, nullptr, 0);
+ if (Fd.OpenDescriptor(fd, FileFd::ReadOnly, none) == false)
+ return false;
+ Fd.SetFileName(File);
+ return true;
+}
+ /*}}}*/
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index 5e857b5c8..19b4ed49e 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -87,7 +87,28 @@ class FileFd
}
bool Read(void *To,unsigned long long Size,unsigned long long *Actual = 0);
bool static Read(int const Fd, void *To, unsigned long long Size, unsigned long long * const Actual = 0);
+ /** read a complete line or until buffer is full
+ *
+ * The buffer will always be \\0 terminated, so at most Size-1 characters are read.
+ * If the buffer holds a complete line the last character (before \\0) will be
+ * the newline character \\n otherwise the line was longer than the buffer.
+ *
+ * @param To buffer which will hold the line
+ * @param Size of the buffer to fill
+ * @param \b nullptr is returned in error cases, otherwise
+ * the parameter \b To now filled with the line.
+ */
char* ReadLine(char *To, unsigned long long const Size);
+ /** read a complete line from the file
+ *
+ * Similar to std::getline() the string does \b not include
+ * the newline, but just the content of the line as the newline
+ * is not needed to distinguish cases as for the other #ReadLine method.
+ *
+ * @param To string which will hold the line
+ * @return \b true if successful, otherwise \b false
+ */
+ bool ReadLine(std::string &To);
bool Flush();
bool Write(const void *From,unsigned long long Size);
bool static Write(int Fd, const void *From, unsigned long long Size);
@@ -140,6 +161,7 @@ class FileFd
inline bool Eof() {return (Flags & HitEof) == HitEof;};
inline bool IsCompressed() {return (Flags & Compressed) == Compressed;};
inline std::string &Name() {return FileName;};
+ inline void SetFileName(std::string const &name) { FileName = name; };
FileFd(std::string FileName,unsigned int const Mode,unsigned long AccessMode = 0666);
FileFd(std::string FileName,unsigned int const Mode, CompressMode Compress, unsigned long AccessMode = 0666);
@@ -256,5 +278,6 @@ std::vector<std::string> Glob(std::string const &pattern, int flags=0);
bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode, bool CaptureStderr);
bool Popen(const char* Args[], FileFd &Fd, pid_t &Child, FileFd::OpenMode Mode);
+APT_HIDDEN bool OpenConfigurationFileFd(std::string const &File, FileFd &Fd);
#endif
diff --git a/apt-pkg/contrib/netrc.cc b/apt-pkg/contrib/netrc.cc
index 88027c989..27511d413 100644
--- a/apt-pkg/contrib/netrc.cc
+++ b/apt-pkg/contrib/netrc.cc
@@ -14,205 +14,129 @@
#include <config.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/fileutl.h>
#include <apt-pkg/strutl.h>
#include <iostream>
-#include <pwd.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
#include "netrc.h"
-using std::string;
-
/* Get user and password from .netrc when given a machine name */
-
-enum {
- NOTHING,
- HOSTFOUND, /* the 'machine' keyword was found */
- HOSTCOMPLETE, /* the machine name following the keyword was found too */
- HOSTVALID, /* this is "our" machine! */
- HOSTEND /* LAST enum */
-};
-
-/* make sure we have room for at least this size: */
-#define LOGINSIZE 256
-#define PASSWORDSIZE 256
-#define NETRC DOT_CHAR "netrc"
-
-/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
-static int parsenetrc_string (char *host, std::string &login, std::string &password, char *netrcfile = NULL)
+bool MaybeAddAuth(FileFd &NetRCFile, URI &Uri)
{
- FILE *file;
- int retcode = 1;
- int specific_login = (login.empty() == false);
- bool netrc_alloc = false;
-
- if (!netrcfile) {
- char const * home = getenv ("HOME"); /* portable environment reader */
-
- if (!home) {
- struct passwd *pw;
- pw = getpwuid (geteuid ());
- if(pw)
- home = pw->pw_dir;
- }
-
- if (!home)
- return -1;
-
- if (asprintf (&netrcfile, "%s%s%s", home, DIR_CHAR, NETRC) == -1 || netrcfile == NULL)
- return -1;
- else
- netrc_alloc = true;
- }
-
- file = fopen (netrcfile, "r");
- if(file) {
- char *tok;
- char *tok_buf;
- bool done = false;
- char *netrcbuffer = NULL;
- size_t netrcbuffer_size = 0;
-
- int state = NOTHING;
- char state_login = 0; /* Found a login keyword */
- char state_password = 0; /* Found a password keyword */
- int state_our_login = false; /* With specific_login,
- found *our* login name */
-
- while (!done && getline(&netrcbuffer, &netrcbuffer_size, file) != -1) {
- tok = strtok_r (netrcbuffer, " \t\n", &tok_buf);
- while (!done && tok) {
- if(login.empty() == false && password.empty() == false) {
- done = true;
- break;
- }
-
- switch(state) {
- case NOTHING:
- if (!strcasecmp ("machine", tok)) {
- /* the next tok is the machine name, this is in itself the
- delimiter that starts the stuff entered for this machine,
- after this we need to search for 'login' and
- 'password'. */
- state = HOSTFOUND;
- }
- break;
- case HOSTFOUND:
- /* extended definition of a "machine" if we have a "/"
- we match the start of the string (host.startswith(token) */
- if ((strchr(host, '/') && strstr(host, tok) == host) ||
- (!strcasecmp (host, tok))) {
- /* and yes, this is our host! */
- state = HOSTVALID;
- retcode = 0; /* we did find our host */
- }
- else
- /* not our host */
- state = NOTHING;
- break;
- case HOSTVALID:
- /* we are now parsing sub-keywords regarding "our" host */
- if (state_login) {
- if (specific_login)
- state_our_login = !strcasecmp (login.c_str(), tok);
- else
- login = tok;
- state_login = 0;
- } else if (state_password) {
- if (state_our_login || !specific_login)
- password = tok;
- state_password = 0;
- } else if (!strcasecmp ("login", tok))
- state_login = 1;
- else if (!strcasecmp ("password", tok))
- state_password = 1;
- else if(!strcasecmp ("machine", tok)) {
- /* ok, there's machine here go => */
- state = HOSTFOUND;
- state_our_login = false;
- }
- break;
- } /* switch (state) */
-
- tok = strtok_r (NULL, " \t\n", &tok_buf);
- } /* while(tok) */
- } /* while getline() */
-
- free(netrcbuffer);
- fclose(file);
- }
-
- if (netrc_alloc)
- free(netrcfile);
-
- return retcode;
-}
-
-void maybe_add_auth (URI &Uri, string NetRCFile)
-{
- if (_config->FindB("Debug::Acquire::netrc", false) == true)
- std::clog << "maybe_add_auth: " << (string)Uri
- << " " << NetRCFile << std::endl;
- if (Uri.Password.empty () == true || Uri.User.empty () == true)
- {
- if (NetRCFile.empty () == false)
- {
- std::string login, password;
- char *netrcfile = strdup(NetRCFile.c_str());
-
- // first check for a generic host based netrc entry
- char *host = strdup(Uri.Host.c_str());
- if (host && parsenetrc_string(host, login, password, netrcfile) == 0)
+ if (Uri.User.empty() == false || Uri.Password.empty() == false)
+ return true;
+ if (NetRCFile.IsOpen() == false || NetRCFile.Failed())
+ return false;
+ auto const Debug = _config->FindB("Debug::Acquire::netrc", false);
+
+ std::string lookfor;
+ if (Uri.Port != 0)
+ strprintf(lookfor, "%s:%i%s", Uri.Host.c_str(), Uri.Port, Uri.Path.c_str());
+ else
+ lookfor.append(Uri.Host).append(Uri.Path);
+
+ enum
+ {
+ NO,
+ MACHINE,
+ GOOD_MACHINE,
+ LOGIN,
+ PASSWORD
+ } active_token = NO;
+ std::string line;
+ while (NetRCFile.Eof() == false || line.empty() == false)
+ {
+ if (line.empty())
{
- if (_config->FindB("Debug::Acquire::netrc", false) == true)
- std::clog << "host: " << host
- << " user: " << login
- << " pass-size: " << password.size()
- << std::endl;
- Uri.User = login;
- Uri.Password = password;
- free(netrcfile);
- free(host);
- return;
+ if (NetRCFile.ReadLine(line) == false)
+ break;
+ else if (line.empty())
+ continue;
}
- free(host);
-
- // if host did not work, try Host+Path next, this will trigger
- // a lookup uri.startswith(host) in the netrc file parser (because
- // of the "/"
- char *hostpath = strdup((Uri.Host + Uri.Path).c_str());
- if (hostpath && parsenetrc_string(hostpath, login, password, netrcfile) == 0)
+ auto tokenend = line.find_first_of("\t ");
+ std::string token;
+ if (tokenend != std::string::npos)
+ {
+ token = line.substr(0, tokenend);
+ line.erase(0, tokenend + 1);
+ }
+ else
+ std::swap(line, token);
+ if (token.empty())
+ continue;
+ switch (active_token)
{
- if (_config->FindB("Debug::Acquire::netrc", false) == true)
- std::clog << "hostpath: " << hostpath
- << " user: " << login
- << " pass-size: " << password.size()
- << std::endl;
- Uri.User = login;
- Uri.Password = password;
+ case NO:
+ if (token == "machine")
+ active_token = MACHINE;
+ break;
+ case MACHINE:
+ if (token.find('/') == std::string::npos)
+ {
+ if (Uri.Port != 0 && Uri.Host == token)
+ active_token = GOOD_MACHINE;
+ else if (lookfor.compare(0, lookfor.length() - Uri.Path.length(), token) == 0)
+ active_token = GOOD_MACHINE;
+ else
+ active_token = NO;
+ }
+ else
+ {
+ if (APT::String::Startswith(lookfor, token))
+ active_token = GOOD_MACHINE;
+ else
+ active_token = NO;
+ }
+ break;
+ case GOOD_MACHINE:
+ if (token == "login")
+ active_token = LOGIN;
+ else if (token == "password")
+ active_token = PASSWORD;
+ else if (token == "machine")
+ {
+ if (Debug)
+ std::clog << "MaybeAddAuth: Found matching host adding '" << Uri.User << "' and '" << Uri.Password << "' for "
+ << (std::string)Uri << " from " << NetRCFile.Name() << std::endl;
+ return true;
+ }
+ break;
+ case LOGIN:
+ std::swap(Uri.User, token);
+ active_token = GOOD_MACHINE;
+ break;
+ case PASSWORD:
+ std::swap(Uri.Password, token);
+ active_token = GOOD_MACHINE;
+ break;
}
- free(netrcfile);
- free(hostpath);
- }
- }
+ }
+ if (active_token == GOOD_MACHINE)
+ {
+ if (Debug)
+ std::clog << "MaybeAddAuth: Found matching host adding '" << Uri.User << "' and '" << Uri.Password << "' for "
+ << (std::string)Uri << " from " << NetRCFile.Name() << std::endl;
+ return true;
+ }
+ else if (active_token == NO)
+ {
+ if (Debug)
+ std::clog << "MaybeAddAuth: Found no matching host for "
+ << (std::string)Uri << " from " << NetRCFile.Name() << std::endl;
+ return true;
+ }
+ else if (Debug)
+ std::clog << "MaybeAddAuth: Found no matching host (syntax error: " << active_token << ") for "
+ << (std::string)Uri << " from " << NetRCFile.Name() << std::endl;
+ return false;
}
-#ifdef DEBUG
-int main(int argc, char* argv[])
+void maybe_add_auth(URI &Uri, std::string NetRCFile)
{
- char login[64] = "";
- char password[64] = "";
-
- if(argc < 2)
- return -1;
-
- if(0 == parsenetrc (argv[1], login, password, argv[2])) {
- printf("HOST: %s LOGIN: %s PASSWORD: %s\n", argv[1], login, password);
- }
+ if (FileExists(NetRCFile) == false)
+ return;
+ FileFd fd;
+ if (fd.Open(NetRCFile, FileFd::ReadOnly))
+ MaybeAddAuth(fd, Uri);
}
-#endif
diff --git a/apt-pkg/contrib/netrc.h b/apt-pkg/contrib/netrc.h
index b5b56f5d4..46d8cab3d 100644
--- a/apt-pkg/contrib/netrc.h
+++ b/apt-pkg/contrib/netrc.h
@@ -22,10 +22,15 @@
#include <apt-pkg/strutl.h>
#endif
+#ifndef APT_15_CLEANER_HEADERS
#define DOT_CHAR "."
#define DIR_CHAR "/"
+#endif
class URI;
+class FileFd;
-void maybe_add_auth (URI &Uri, std::string NetRCFile);
+APT_DEPRECATED_MSG("Use FileFd-based MaybeAddAuth instead")
+void maybe_add_auth(URI &Uri, std::string NetRCFile);
+bool MaybeAddAuth(FileFd &NetRCFile, URI &Uri);
#endif