XRootD
XrdOucUtils.cc File Reference
#include <cctype>
#include <grp.h>
#include <cstdio>
#include <list>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <charconv>
#include <random>
#include <regex.h>
#include <fcntl.h>
#include <math.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <map>
#include <iomanip>
#include "XrdNet/XrdNetUtils.hh"
#include "XrdOuc/XrdOucCRC.hh"
#include "XrdOuc/XrdOucEnv.hh"
#include "XrdOuc/XrdOucSHA3.hh"
#include "XrdOuc/XrdOucStream.hh"
#include "XrdOuc/XrdOucString.hh"
#include "XrdOuc/XrdOucUtils.hh"
#include "XrdOuc/XrdOucPrivateUtils.hh"
#include "XrdSys/XrdSysE2T.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdSys/XrdSysPlatform.hh"
#include "XrdSys/XrdSysPthread.hh"
+ Include dependency graph for XrdOucUtils.cc:

Go to the source code of this file.

Macros

#define ENODATA   ENOATTR
 
#define SHFT(k)   if (n >= (1ULL << k)) { i += k; n >>= k; }
 
#define SHFT(k, m)   if (n >= m) { i += k; n /= m; }
 

Functions

static int from_hex (char c)
 
static bool is_rfc3986_unreserved (unsigned char c)
 
static bool is_token_character (int c)
 
std::string obfuscateAuth (const std::string &input)
 
void splitHostCgi (std::string_view target, std::string &host, std::string &cgi)
 
void stripCgi (std::string &url, const std::unordered_set< std::string > &cgiKeys)
 
void stripCgi (XrdOucString &url, const std::unordered_set< std::string > &cgiKeys)
 

Macro Definition Documentation

◆ ENODATA

#define ENODATA   ENOATTR

Definition at line 69 of file XrdOucUtils.cc.

◆ SHFT [1/2]

#define SHFT (   k)    if (n >= (1ULL << k)) { i += k; n >>= k; }

◆ SHFT [2/2]

#define SHFT (   k,
  m 
)    if (n >= m) { i += k; n /= m; }

Function Documentation

◆ from_hex()

static int from_hex ( char  c)
static

Definition at line 1700 of file XrdOucUtils.cc.

1701 {
1702  if (c >= '0' && c <= '9') return c - '0';
1703  if (c >= 'A' && c <= 'F') return c - 'A' + 10;
1704  if (c >= 'a' && c <= 'f') return c - 'a' + 10;
1705  return -1;
1706 }

Referenced by XrdOucUtils::UrlDecode().

+ Here is the caller graph for this function:

◆ is_rfc3986_unreserved()

static bool is_rfc3986_unreserved ( unsigned char  c)
static

Definition at line 1669 of file XrdOucUtils.cc.

1670 {
1671  return std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~';
1672 }

Referenced by XrdOucUtils::UrlEncode().

+ Here is the caller graph for this function:

◆ is_token_character()

static bool is_token_character ( int  c)
static

Returns a boolean indicating whether 'c' is a valid token character or not. See https://datatracker.ietf.org/doc/html/rfc6750#section-2.1 for details.

Definition at line 1615 of file XrdOucUtils.cc.

1616 {
1617  if (isalnum(c))
1618  return true;
1619 
1620  static constexpr char token_chars[] = "-._~+/=:%";
1621 
1622  for (char ch : token_chars)
1623  if (c == ch)
1624  return true;
1625 
1626  return false;
1627 }

Referenced by obfuscateAuth(), and stripCgi().

+ Here is the caller graph for this function:

◆ obfuscateAuth()

std::string obfuscateAuth ( const std::string &  input)

This function obfuscates away authz= cgi elements and/or HTTP authorization headers from URL or other log line strings which might contain them.

Parameters
inputthe string to obfuscate
Returns
the string with token values obfuscated

Definition at line 1637 of file XrdOucUtils.cc.

1638 {
1639  static const regex_t auth_regex = []() {
1640  constexpr char re[] =
1641  "(access_token=|authz=|(transferheader)?(www-|proxy-)?auth(orization|enticate)([[:space:]]*:[[:space:]]*|[[:space:]]+))"
1642  "(Bearer([[:space:]]|%20)?(token([[:space:]]|%20)?)?)?";
1643 
1644  regex_t regex;
1645 
1646  if (regcomp(&regex, re, REG_EXTENDED | REG_ICASE) != 0)
1647  throw std::runtime_error("Failed to compile regular expression");
1648 
1649  return regex;
1650  }();
1651 
1652  regmatch_t match;
1653  size_t offset = 0;
1654  std::string redacted;
1655  const char *const text = input.c_str();
1656 
1657  while (regexec(&auth_regex, text + offset, 1, &match, 0) == 0) {
1658  redacted.append(text + offset, match.rm_eo).append("REDACTED");
1659 
1660  offset += match.rm_eo;
1661 
1662  while (offset < input.size() && is_token_character(input[offset]))
1663  ++offset;
1664  }
1665 
1666  return redacted.append(text + offset);
1667 }
static bool is_token_character(int c)

References is_token_character().

Referenced by XrdPfc::Cache::Attach(), XrdClHttp::HeaderBuilder::Build(), XrdPosixXrootd::Close(), XrdPosixFile::DelayedDestroy(), XrdPosixPrepIO::Disable(), XrdPssSys::FSctl(), XrdPssCks::Get(), XrdCl::URL::GetObfuscatedURL(), XrdCl::Utils::LogPropertyList(), main(), XrdPssSys::Mkdir(), XrdPssFile::Open(), XrdPssDir::Opendir(), XrdCl::CopyProcess::Prepare(), XrdHttpProtocol::Process(), XrdHttpReq::ProcessHTTPReq(), XrdPssSys::Remdir(), XrdPssSys::Rename(), XrdCl::Message::SetDescription(), XrdPssSys::Stat(), XrdPssSys::Truncate(), and XrdPssSys::Unlink().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ splitHostCgi()

void splitHostCgi ( std::string_view  target,
std::string &  host,
std::string &  cgi 
)

Split a "host[?cgi]" string at its first '?'.

Parameters
targetthe "host[?cgi]" string to split
hostoutput: the portion before the first '?', or the whole string when target contains no '?'
cgioutput: the first '?' and everything after it (so it begins with '?'), or empty when target contains no '?'

Definition at line 1778 of file XrdOucUtils.cc.

1780 {
1781  const size_t q = target.find('?');
1782  if (q == std::string::npos) {host.assign(target); cgi.clear();}
1783  else {host.assign(target.data(), q);
1784  cgi.assign(target.data() + q, target.size() - q);
1785  }
1786 }

Referenced by XrdXrootdRedirHelper::Redirect().

+ Here is the caller graph for this function:

◆ stripCgi() [1/2]

void stripCgi ( std::string &  url,
const std::unordered_set< std::string > &  cgiKeys 
)

Strip selected CGI elements (e.g. "authz=...") from a string/URL.

Parameters
urlthe string/URL to sanitize
cgiKeysCGI parameter names to remove (without the trailing '=')

Definition at line 1744 of file XrdOucUtils.cc.

1745 {
1746  for (const auto &key : cgiKeys) {
1747  if (key.empty())
1748  continue;
1749 
1750  const std::string needle = key + "=";
1751  size_t spos = 0, epos = 0;
1752 
1753  while ((spos = url.find(needle, spos)) != std::string::npos) {
1754  epos = spos;
1755  while (epos < url.size() && is_token_character(url[epos]))
1756  ++epos;
1757  url.erase(spos, epos - spos);
1758  }
1759  }
1760 
1761  // If a stripped CGI was the first element, remove the extra &
1762  size_t spos = 0;
1763  if ((spos = url.find("?&")) != std::string::npos)
1764  url.erase(spos + 1, 1);
1765 
1766  // If stripping removed the only query parameter, remove the dangling ?
1767  if (!url.empty() && url.back() == '?')
1768  url.pop_back();
1769 }

References is_token_character().

Referenced by XrdHttpReq::Redir(), and stripCgi().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ stripCgi() [2/2]

void stripCgi ( XrdOucString &  url,
const std::unordered_set< std::string > &  cgiKeys 
)

Definition at line 1771 of file XrdOucUtils.cc.

1772 {
1773  std::string tmp = url.c_str();
1774  stripCgi(tmp, cgiKeys);
1775  url = tmp.c_str();
1776 }
void stripCgi(std::string &url, const std::unordered_set< std::string > &cgiKeys)
const char * c_str() const

References XrdOucString::c_str(), and stripCgi().

+ Here is the call graph for this function: