diff options
Diffstat (limited to '')
-rw-r--r-- | apt-pkg/contrib/netrc.cc | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/apt-pkg/contrib/netrc.cc b/apt-pkg/contrib/netrc.cc new file mode 100644 index 0000000..ec694da --- /dev/null +++ b/apt-pkg/contrib/netrc.cc @@ -0,0 +1,173 @@ +// -*- mode: cpp; mode: fold -*- +// SPDX-License-Identifier: GPL-2.0+ +// Description /*{{{*/ +/* ###################################################################### + + netrc file parser - returns the login and password of a give host in + a specified netrc-type file + + This file had this historic note, but now includes further changes + under the GPL-2.0+: + + Originally written by Daniel Stenberg, <daniel@haxx.se>, et al. and + placed into the Public Domain, do with it what you will. + + ##################################################################### */ + /*}}}*/ +#include <config.h> +#include <apti18n.h> + +#include <apt-pkg/configuration.h> +#include <apt-pkg/error.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/strutl.h> + +#include <iostream> + +#include "netrc.h" + +/* Get user and password from .netrc when given a machine name */ +bool MaybeAddAuth(FileFd &NetRCFile, URI &Uri) +{ + 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) + { + bool protocolSpecified = false; + + if (line.empty()) + { + if (NetRCFile.ReadLine(line) == false) + break; + else if (line.empty()) + continue; + } + 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) + { + case NO: + if (token == "machine") + active_token = MACHINE; + break; + case MACHINE: + // If token contains a protocol: Check it first, and strip it away if + // it matches. If it does not match, ignore this stanza. + // If there is no protocol, only allow https protocols. + protocolSpecified = token.find("://") != std::string::npos; + if (protocolSpecified) + { + if (not APT::String::Startswith(token, Uri.Access + "://")) + { + active_token = NO; + break; + } + token.erase(0, Uri.Access.length() + 3); + } + + 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; + } + + if (active_token == GOOD_MACHINE && not protocolSpecified) + { + if (Uri.Access != "https" && Uri.Access != "tor+https") + { + _error->Warning(_("%s: Credentials for %s match, but the protocol is not encrypted. Annotate with %s:// to use."), NetRCFile.Name().c_str(), token.c_str(), Uri.Access.c_str()); + 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; + } + } + 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: token:"; + switch (active_token) + { + case NO: std::clog << "NO"; break; + case MACHINE: std::clog << "MACHINE"; break; + case GOOD_MACHINE: std::clog << "GOOD_MACHINE"; break; + case LOGIN: std::clog << "LOGIN"; break; + case PASSWORD: std::clog << "PASSWORD"; break; + } + std::clog << ") for " << (std::string)Uri << " from " << NetRCFile.Name() << std::endl; + } + return false; +} |