//------------------------------------------------------------------------------
//! @file fusexrdlogin.cc
//! @author Andreas-Joachim Peters CERN
//! @brief Class providing the login user name for an XRootD fusex connection
//------------------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2017 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
#include "fusexrdlogin.hh"
#include "eosfuse.hh"
#include "common/Macros.hh"
#include "common/SymKeys.hh"
#include "misc/FuseId.hh"
#include "auth/Logbook.hh"
#include "auth/LoginIdentifier.hh"
#include
#include
#ifdef __APPLE__
#define ECHRNG 44
#endif
std::unique_ptr fusexrdlogin::authGroup;
ProcessCache* fusexrdlogin::processCache = nullptr;
void fusexrdlogin::initializeProcessCache(const CredentialConfig& config)
{
authGroup.reset(new AuthenticationGroup(config));
processCache = authGroup->processCache();
}
std::string fusexrdlogin::fillExeName(const std::string& execname)
{
auto base_name = [](std::string const & path) {
return path.substr(path.find_last_of("/\\") + 1);
};
std::regex safeReg("[/\\w.]+");
std::string exe = execname;
if (execname.length() > 32) {
exe = base_name(execname);
}
if (std::regex_match(exe, safeReg)) {
return exe;
} else {
std::string base64_string = "base64";
std::string base64in = exe;
SymKey::Base64(base64in, base64_string);
return base64_string;
}
}
int fusexrdlogin::loginurl(XrdCl::URL& url,
XrdCl::URL::ParamsMap& paramsMap,
fuse_req_t req,
fuse_ino_t ino,
bool root_squash,
int connection_id)
{
fuse_id id(req);
return loginurl(url, paramsMap, id.uid, id.gid, id.pid, root_squash,
connection_id);
}
std::string fusexrdlogin::executable(fuse_req_t req) {
fuse_id id(req);
Logbook logbook(true);
ProcessSnapshot snapshot =
(id.pid)?processCache->retrieve(id.pid, id.uid, id.gid,
false, logbook) : 0;
if (snapshot) {
return fillExeName(snapshot->getExe());
} else {
return "unknown";
}
}
int fusexrdlogin::loginurl(XrdCl::URL& url,
XrdCl::URL::ParamsMap& paramsMap,
uid_t uid,
gid_t gid,
pid_t pid,
fuse_ino_t ino,
bool root_squash,
int connection_id)
{
fuse_id id;
id.uid = uid;
id.gid = gid;
id.pid = pid;
bool fallback = false;
std::string username = "nobody";
paramsMap["fuse.ver"] = VERSION;
paramsMap["fuse.pid"] = std::to_string(id.pid);
paramsMap["fuse.uid"] = std::to_string(id.uid);
paramsMap["fuse.gid"] = std::to_string(id.gid);
ProcessSnapshot snapshot = processCache->retrieve(id.pid, id.uid, id.gid,
false);
if (snapshot) {
username = snapshot->getBoundIdentity()->getLogin().getStringID();
snapshot->getBoundIdentity()->getCreds()->toXrdParams(paramsMap);
paramsMap["fuse.exe"] = fillExeName(snapshot->getExe());
} else {
if (uid && EosFuse::Instance().Config().auth.use_user_unix) {
// fallback to the unix user if we have a problem snapshotting a process
LoginIdentifier lIdentifier (id.uid, id.gid, id.pid, 0);
username = lIdentifier.describe();
paramsMap["xrd.wantprot"] = "unix";
paramsMap["xrdcl.secuid"] = std::to_string(uid);
paramsMap["xrdcl.secgid"] = std::to_string(gid);
fallback = true;
}
}
url.SetUserName(username);
int rc = 0;
if (fallback) {
eos_static_warning("[unix-fallback] %s uid=%u gid=%u pid=%u user-name=%s url=%s",
EosFuse::dump(id, ino, 0, rc).c_str(),
id.uid,
id.gid,
id.pid,
username.c_str(),
url.GetURL().c_str()
);
} else {
eos_static_notice("%s uid=%u gid=%u rc=%d user-name=%s url=%s",
EosFuse::dump(id, ino, 0, rc).c_str(),
id.uid,
id.gid,
rc,
username.c_str(),
url.GetURL().c_str()
);
}
return rc;
}
std::string fusexrdlogin::xrd_login(fuse_req_t req)
{
fuse_id id(req);
ProcessSnapshot snapshot = processCache->retrieve(id.pid, id.uid, id.gid,
false);
std::string login;
if (snapshot) {
login = snapshot->getXrdLogin();
} else {
login = "unix";
}
eos_static_info("uid=%u gid=%u xrd-login=%s",
id.uid,
id.gid,
login.c_str()
);
return login;
}
std::string fusexrdlogin::secret(fuse_req_t req)
{
fuse_id id(req);
ProcessSnapshot snapshot = processCache->retrieve(id.pid, id.uid, id.gid,
false);
if (snapshot) {
return snapshot->getBoundIdentity()->getCreds()->getKey();
}
return "";
}
std::string fusexrdlogin::environment(fuse_req_t req)
{
fuse_id id(req);
ProcessSnapshot snapshot = processCache->retrieve(id.pid, id.uid, id.gid,
false);
std::string envtoset;
XrdCl::URL::ParamsMap paramsMap;
if (snapshot) {
snapshot->getBoundIdentity()->getCreds()->toXrdParams(paramsMap);
}
if (paramsMap["xrd.k5ccname"] != "") {
envtoset += "env KRB5CCNAME=";
envtoset += paramsMap["xrd.k5ccname"];
} else {
if (paramsMap["xrd.gsiusrpxy"] != "") {
envtoset += "env X509_USER_PROXY=";
envtoset += paramsMap["xrd.gsiusrpxy"];
}
}
return envtoset;
}
/*----------------------------------------------------------------------------*/