| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/authz/authz_session.h |
| Date: | 2025-10-26 02:35:25 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 16 | 16 | 100.0% |
| Branches: | 6 | 8 | 75.0% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * This file is part of the CernVM File System. | ||
| 3 | */ | ||
| 4 | |||
| 5 | #ifndef CVMFS_AUTHZ_AUTHZ_SESSION_H_ | ||
| 6 | #define CVMFS_AUTHZ_AUTHZ_SESSION_H_ | ||
| 7 | |||
| 8 | #include <inttypes.h> | ||
| 9 | #include <pthread.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | |||
| 12 | #include <string> | ||
| 13 | |||
| 14 | #include "authz/authz.h" | ||
| 15 | #include "duplex_testing.h" | ||
| 16 | #include "smallhash.h" | ||
| 17 | #include "statistics.h" | ||
| 18 | #include "util/murmur.hxx" | ||
| 19 | #include "util/single_copy.h" | ||
| 20 | |||
| 21 | class AuthzFetcher; | ||
| 22 | |||
| 23 | // TODO(jblomer): add audit log | ||
| 24 | |||
| 25 | /** | ||
| 26 | * The authorization manager maintains a list of sessions (sid and its birthday) | ||
| 27 | * and their associated credentials. It is used to pass the credentials to the | ||
| 28 | * download module and to control access to the repository. Every credential | ||
| 29 | * has a membership (a string) associated with it. The credential is thereby | ||
| 30 | * confirmed to be a member of the specified group. The group/membership can | ||
| 31 | * be anything, for instance a role in a certificate. It is stored in the cvmfs | ||
| 32 | * root file catalog. | ||
| 33 | * | ||
| 34 | * An AuthzFetcher is used to gather credentials that are not cached. Note that | ||
| 35 | * the credentials are fetched using original pid/uid/gid but cached under the | ||
| 36 | * session. | ||
| 37 | */ | ||
| 38 | class AuthzSessionManager : SingleCopy { | ||
| 39 | FRIEND_TEST(T_AuthzSession, GetPidInfo); | ||
| 40 | FRIEND_TEST(T_AuthzSession, LookupAuthzData); | ||
| 41 | FRIEND_TEST(T_AuthzSession, LookupSessionKey); | ||
| 42 | |||
| 43 | public: | ||
| 44 | static AuthzSessionManager *Create(AuthzFetcher *authz_fetcher, | ||
| 45 | perf::Statistics *statistics); | ||
| 46 | ~AuthzSessionManager(); | ||
| 47 | |||
| 48 | AuthzToken *GetTokenCopy(const pid_t pid, const std::string &membership); | ||
| 49 | bool IsMemberOf(const pid_t pid, const std::string &membership); | ||
| 50 | |||
| 51 | /** | ||
| 52 | * When the membership string in the root file catalog changes, all entries in | ||
| 53 | * the cache become invalid because they only vouch for the previous | ||
| 54 | * membership entry. This function is called by MountPoint::ReEvaluateAuthz. | ||
| 55 | */ | ||
| 56 | void ClearSessionCache(); | ||
| 57 | |||
| 58 | private: | ||
| 59 | /** | ||
| 60 | * Sweep caches from old entries not more often than every 5 seconds. | ||
| 61 | */ | ||
| 62 | static const unsigned kSweepInterval = 5; | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Pid to session information is cached for 2 minutes. | ||
| 66 | */ | ||
| 67 | static const unsigned kPidLifetime = 120; | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Extended information on a PID. | ||
| 71 | */ | ||
| 72 | struct PidKey { | ||
| 73 | 23967 | PidKey() : pid(-1), uid(-1), gid(-1), sid(-1), pid_bday(0), deadline(0) { } | |
| 74 | pid_t pid; | ||
| 75 | uid_t uid; | ||
| 76 | gid_t gid; | ||
| 77 | pid_t sid; | ||
| 78 | uint64_t pid_bday; | ||
| 79 | uint64_t deadline; | ||
| 80 | |||
| 81 | 3624 | bool operator==(const PidKey &other) const { | |
| 82 |
3/4✓ Branch 0 taken 3432 times.
✓ Branch 1 taken 192 times.
✓ Branch 2 taken 3432 times.
✗ Branch 3 not taken.
|
3624 | return (pid == other.pid) && (pid_bday == other.pid_bday); |
| 83 | } | ||
| 84 | |||
| 85 | 3024 | bool operator!=(const PidKey &other) const { return !(*this == other); } | |
| 86 | }; | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Extended information on an SID. | ||
| 90 | */ | ||
| 91 | struct SessionKey { | ||
| 92 | 46677 | SessionKey() : sid(-1), sid_bday(0) { } | |
| 93 | pid_t sid; | ||
| 94 | uint64_t sid_bday; | ||
| 95 | |||
| 96 | 24861 | bool operator==(const SessionKey &other) const { | |
| 97 |
3/4✓ Branch 0 taken 24501 times.
✓ Branch 1 taken 360 times.
✓ Branch 2 taken 24501 times.
✗ Branch 3 not taken.
|
24861 | return (sid == other.sid) && (sid_bday == other.sid_bday); |
| 98 | } | ||
| 99 | |||
| 100 | 23877 | bool operator!=(const SessionKey &other) const { return !(*this == other); } | |
| 101 | }; | ||
| 102 | |||
| 103 | 432 | static uint32_t HashPidKey(const PidKey &key) { | |
| 104 | struct { | ||
| 105 | uint64_t bday; | ||
| 106 | pid_t pid; | ||
| 107 | } __attribute__((packed)) key_info; | ||
| 108 | 432 | key_info.pid = key.pid; | |
| 109 | 432 | key_info.bday = key.pid_bday; | |
| 110 | 432 | return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f); | |
| 111 | } | ||
| 112 | |||
| 113 | 720 | static uint32_t HashSessionKey(const SessionKey &key) { | |
| 114 | struct { | ||
| 115 | uint64_t bday; | ||
| 116 | pid_t pid; | ||
| 117 | } __attribute__((packed)) key_info; | ||
| 118 | 720 | key_info.pid = key.sid; | |
| 119 | 720 | key_info.bday = key.sid_bday; | |
| 120 | 720 | return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f); | |
| 121 | } | ||
| 122 | |||
| 123 | AuthzSessionManager(); | ||
| 124 | |||
| 125 | bool GetPidInfo(pid_t pid, PidKey *pid_key); | ||
| 126 | bool LookupSessionKey(pid_t pid, PidKey *pid_key, SessionKey *session_key); | ||
| 127 | void MaySweepPids(); | ||
| 128 | void SweepPids(uint64_t now); | ||
| 129 | |||
| 130 | bool LookupAuthzData(const PidKey &pid_key, | ||
| 131 | const SessionKey &session_key, | ||
| 132 | const std::string &membership, | ||
| 133 | AuthzData *authz_data); | ||
| 134 | void MaySweepCreds(); | ||
| 135 | void SweepCreds(uint64_t now); | ||
| 136 | |||
| 137 | /** | ||
| 138 | * Caches (extended) session information for an (extended) pid. | ||
| 139 | */ | ||
| 140 | SmallHashDynamic<PidKey, SessionKey> pid2session_; | ||
| 141 | pthread_mutex_t lock_pid2session_; | ||
| 142 | uint64_t deadline_sweep_pids_; | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Caches credentials corresponding to a session. | ||
| 146 | */ | ||
| 147 | SmallHashDynamic<SessionKey, AuthzData> session2cred_; | ||
| 148 | pthread_mutex_t lock_session2cred_; | ||
| 149 | uint64_t deadline_sweep_creds_; | ||
| 150 | |||
| 151 | /** | ||
| 152 | * The helper that takes care of bringing in credentials from the client | ||
| 153 | * context. | ||
| 154 | */ | ||
| 155 | AuthzFetcher *authz_fetcher_; | ||
| 156 | |||
| 157 | perf::Counter *no_pid_; | ||
| 158 | perf::Counter *no_session_; | ||
| 159 | perf::Counter *n_fetch_; | ||
| 160 | perf::Counter *n_grant_; | ||
| 161 | perf::Counter *n_deny_; | ||
| 162 | }; | ||
| 163 | |||
| 164 | #endif // CVMFS_AUTHZ_AUTHZ_SESSION_H_ | ||
| 165 |