// -*- mode: cpp; mode: fold -*- // Description /*{{{*/ // $Id: netrc.c,v 1.38 2007-11-07 09:21:35 bagder Exp $ /* ###################################################################### netrc file parser - returns the login and password of a give host in a specified netrc-type file 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 <apt-pkg/configuration.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) { 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.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; } } 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; } void maybe_add_auth(URI &Uri, std::string NetRCFile) { if (FileExists(NetRCFile) == false) return; FileFd fd; if (fd.Open(NetRCFile, FileFd::ReadOnly)) MaybeAddAuth(fd, Uri); }