GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/authz/authz_session.h
Date: 2025-06-01 02:36:00
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 "gtest/gtest_prod.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 1082 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 151 bool operator==(const PidKey &other) const {
82
3/4
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 143 times.
✗ Branch 3 not taken.
151 return (pid == other.pid) && (pid_bday == other.pid_bday);
83 }
84
85 126 bool operator!=(const PidKey &other) const { return !(*this == other); }
86 };
87
88 /**
89 * Extended information on an SID.
90 */
91 struct SessionKey {
92 2108 SessionKey() : sid(-1), sid_bday(0) { }
93 pid_t sid;
94 uint64_t sid_bday;
95
96 1112 bool operator==(const SessionKey &other) const {
97
3/4
✓ Branch 0 taken 1097 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1097 times.
✗ Branch 3 not taken.
1112 return (sid == other.sid) && (sid_bday == other.sid_bday);
98 }
99
100 1071 bool operator!=(const SessionKey &other) const { return !(*this == other); }
101 };
102
103 18 static uint32_t HashPidKey(const PidKey &key) {
104 struct {
105 uint64_t bday;
106 pid_t pid;
107 } __attribute__((packed)) key_info;
108 18 key_info.pid = key.pid;
109 18 key_info.bday = key.pid_bday;
110 18 return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f);
111 }
112
113 30 static uint32_t HashSessionKey(const SessionKey &key) {
114 struct {
115 uint64_t bday;
116 pid_t pid;
117 } __attribute__((packed)) key_info;
118 30 key_info.pid = key.sid;
119 30 key_info.bday = key.sid_bday;
120 30 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