1
0
Fork 0
apt/apt-pkg/contrib/netrc.cc
Daniel Baumann 6810ba718b
Adding upstream version 3.0.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-20 21:10:43 +02:00

173 lines
4.8 KiB
C++

// -*- 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;
}