// ----------------------------------------------------------------------
// File: UserCredentials.hh
// Author: Georgios Bitzes - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 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 .*
************************************************************************/
#ifndef EOS_FUSEX_USER_CREDENTIALS_HH
#define EOS_FUSEX_USER_CREDENTIALS_HH
#include "JailIdentifier.hh"
#include "Utils.hh"
#include
#include
#include "common/StringConversion.hh"
//------------------------------------------------------------------------------
// Designates what kind of user credentials we're dealing with:
// - KRB5: Kerberos file-based ticket cache
// - KRK5: Kerberos kernel-keyring-based ticket cache
// - KCM: Kerberos KCM daemon ticket cache
// - X509: GSI user certificates
// - SSS: SSS ticket delegation
// - NOBODY: Identify as nobody, no user credentails whatsoever
// - OAUTH2: oauth2 over sss
// --ZTN: Token authentication
//------------------------------------------------------------------------------
enum class CredentialType : std::uint32_t {
KRB5 = 0,
KRK5,
KCM,
X509,
SSS,
NOBODY,
OAUTH2,
ZTN,
INVALID
};
//------------------------------------------------------------------------------
// Convert CredentialType to string
//------------------------------------------------------------------------------
inline std::string credentialTypeAsString(CredentialType type) {
switch(type) {
case CredentialType::KRB5: {
return "krb5";
}
case CredentialType::KRK5: {
return "krk5";
}
case CredentialType::KCM: {
return "kcm";
}
case CredentialType::X509: {
return "x509";
}
case CredentialType::SSS: {
return "sss";
}
case CredentialType::OAUTH2: {
return "oauth2";
}
case CredentialType::ZTN: {
return "ztn";
}
case CredentialType::NOBODY: {
return "nobody";
}
case CredentialType::INVALID: {
return "invadid";
}
}
THROW("should never reach here");
}
//------------------------------------------------------------------------------
// This class stores information about an instance of user credentials. The
// information contained within _must be sufficient_ to create an instance
// of TrustedCredentials, after validation.
//
// UserCredentials could be all kinds of wrong, as it's derived directly
// by user-provided data: Maybe credential files don't exist, or they have
// wrong permissions, etc, so we cannot use it yet.
//
// TrustedCredentials = validated UserCredentials with a stamp of approval, but
// not yet bound to a connection.
//
// BoundIdentity = TrustedCredentials bound to a LoginIdentifier.
//------------------------------------------------------------------------------
struct UserCredentials {
//----------------------------------------------------------------------------
// Private constructor: Use the methods above to create such an object.
//----------------------------------------------------------------------------
UserCredentials() {
type = CredentialType::INVALID;
// fname, keyring, endorsement default-initialized to empty
uid = 0;
gid = 0;
}
//----------------------------------------------------------------------------
// Constructor: Make a KRB5 object.
// We only need two pieces of information: The path at which the ticket cache
// resides in, and the uid to validate file permissions.
//----------------------------------------------------------------------------
static UserCredentials MakeKrb5(const JailIdentifier& jail,
const std::string& path, uid_t uid, gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::KRB5;
retval.jail = jail;
retval.fname = path;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make a KRK5 object.
// TODO(gbitzes): Actually test this...
//----------------------------------------------------------------------------
static UserCredentials MakeKrk5(const std::string &keyring, uid_t uid, gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::KRK5;
retval.keyring = keyring;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make a KCM object.
// TODO(gbitzes): Actually test this...
//----------------------------------------------------------------------------
static UserCredentials MakeKcm(const std::string &kcm, uid_t uid, gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::KCM;
retval.kcm = kcm;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make a OAUTH2 object.
// TODO(gbitzes): Actually test this...
//----------------------------------------------------------------------------
static UserCredentials MakeOAUTH2(const JailIdentifier& jail,
const std::string& path, uid_t uid, gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::OAUTH2;
retval.jail = jail;
retval.fname = path;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
std::string out;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make an X509 object.
// We only need two pieces of information: The path at which the certificate
// resides in, and the uid to validate file permissions.
//----------------------------------------------------------------------------
static UserCredentials MakeX509(const JailIdentifier& jail,
const std::string &path, uid_t uid, gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::X509;
retval.jail = jail;
retval.fname = path;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make a "nobody" object.
//----------------------------------------------------------------------------
static UserCredentials MakeNobody() {
UserCredentials retval;
retval.type = CredentialType::NOBODY;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make an SSS object.
// Three things required: The endorsement derived through environment
// variables, as well as uid and gid.
//
// TODO: If the global SSS key is not mapped to anyuser / anygroup,
// persisting uid/gid here is pointless.
//----------------------------------------------------------------------------
static UserCredentials MakeSSS(const std::string &endorsement, uid_t uid,
gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::SSS;
retval.endorsement = endorsement;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
return retval;
}
//----------------------------------------------------------------------------
// Constructor: Make a ZTN object.
// We only need two pieces of information: The path at which the ticket cache
// resides in, and the uid to validate file permissions.
//----------------------------------------------------------------------------
static UserCredentials MakeZTN(const JailIdentifier& jail,
const std::string& path, uid_t uid, gid_t gid, const std::string& key) {
UserCredentials retval;
retval.type = CredentialType::ZTN;
retval.jail = jail;
retval.fname = path;
retval.uid = uid;
retval.gid = gid;
retval.secretkey = key;
return retval;
}
//----------------------------------------------------------------------------
// Check if path contains unsafe characters: '&' or '='
//----------------------------------------------------------------------------
bool hasUnsafeCharacters() const {
for(size_t i = 0; i < fname.size(); i++) {
if(fname[i] == '&' || fname[i] == '=') {
return true;
}
}
return false;
}
//----------------------------------------------------------------------------
// The subset of fields actually containing a value depends on the
// CredentialType.
//----------------------------------------------------------------------------
CredentialType type;
JailIdentifier jail; // jail identifier for krb5, x509
std::string fname; // credential filename for krb5, x509
std::string keyring; // kernel keyring for krk5
std::string kcm; // kcm for kcm
std::string endorsement; // endorsement for sss
std::string secretkey; // secret key for encryptions
uid_t uid; // uid for krb5, x509, sss, unix
gid_t gid; // gid for krb5, x509, sss, unix
//----------------------------------------------------------------------------
// Comparator for storing such objects in maps.
//----------------------------------------------------------------------------
bool operator<(const UserCredentials& src) const
{
if (type != src.type) {
return type < src.type;
}
if (fname != src.fname) {
return fname < src.fname;
}
if (keyring != src.keyring) {
return keyring < src.keyring;
}
if (secretkey != src.secretkey) {
return secretkey < src.secretkey;
}
if (endorsement != src.endorsement) {
return endorsement < src.endorsement;
}
if (uid != src.uid) {
return uid < src.uid;
}
return gid < src.gid;
}
//----------------------------------------------------------------------------
// Equality operator
//----------------------------------------------------------------------------
bool operator==(const UserCredentials& src) const
{
return type == src.type &&
jail == src.jail &&
fname == src.fname &&
keyring == src.keyring &&
secretkey == src.secretkey &&
endorsement == src.endorsement &&
uid == src.uid &&
gid == src.gid;
}
//----------------------------------------------------------------------------
// Describe contents
//----------------------------------------------------------------------------
std::string describe() const {
std::stringstream ss;
ss << credentialTypeAsString(type);;
switch(type) {
case CredentialType::KRB5:
case CredentialType::OAUTH2:
case CredentialType::ZTN:
case CredentialType::X509: {
ss << ": " << fname << " for uid=" << uid << ", gid=" << gid << ", secret=" << secretkey <<
", under " << jail.describe();
break;
}
case CredentialType::KRK5: {
ss << ": " << keyring << " for uid=" << uid << ", gid=" << gid << ", secret=" << secretkey;
break;
}
case CredentialType::KCM: {
ss << ": " << kcm << " for uid=" << uid << ", gid=" << gid << ", secret=" << secretkey;
break;
}
case CredentialType::SSS: {
ss << " with endorsement of size " << endorsement.size() <<
", for uid=" << uid << ", gid=" << gid << ", secret=" << secretkey;
break;
}
case CredentialType::NOBODY:
case CredentialType::INVALID: {
ss << ",secret=" << secretkey;
break;
// null
}
}
return ss.str();
}
private:
};
#endif