GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/authz/authz_session.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 20 20 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
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 8 times.
294 return (pid == other.pid) &&
83
1/2
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
294 (pid_bday == other.pid_bday);
84 }
85
86 126 bool operator !=(const PidKey &other) const {
87 126 return !(*this == other);
88 }
89 };
90
91 /**
92 * Extended information on an SID.
93 */
94 struct SessionKey {
95 2108 SessionKey() : sid(-1), sid_bday(0) { }
96 pid_t sid;
97 uint64_t sid_bday;
98
99 1112 bool operator ==(const SessionKey &other) const {
100
2/2
✓ Branch 0 taken 1097 times.
✓ Branch 1 taken 15 times.
2209 return (sid == other.sid) &&
101
1/2
✓ Branch 0 taken 1097 times.
✗ Branch 1 not taken.
2209 (sid_bday == other.sid_bday);
102 }
103
104 1071 bool operator !=(const SessionKey &other) const {
105 1071 return !(*this == other);
106 }
107 };
108
109 18 static uint32_t HashPidKey(const PidKey &key) {
110 struct {
111 uint64_t bday;
112 pid_t pid;
113 } __attribute__((packed)) key_info;
114 18 key_info.pid = key.pid;
115 18 key_info.bday = key.pid_bday;
116 18 return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f);
117 }
118
119 30 static uint32_t HashSessionKey(const SessionKey &key) {
120 struct {
121 uint64_t bday;
122 pid_t pid;
123 } __attribute__((packed)) key_info;
124 30 key_info.pid = key.sid;
125 30 key_info.bday = key.sid_bday;
126 30 return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f);
127 }
128
129 AuthzSessionManager();
130
131 bool GetPidInfo(pid_t pid, PidKey *pid_key);
132 bool LookupSessionKey(pid_t pid, PidKey *pid_key, SessionKey *session_key);
133 void MaySweepPids();
134 void SweepPids(uint64_t now);
135
136 bool LookupAuthzData(const PidKey &pid_key,
137 const SessionKey &session_key,
138 const std::string &membership,
139 AuthzData *authz_data);
140 void MaySweepCreds();
141 void SweepCreds(uint64_t now);
142
143 /**
144 * Caches (extended) session information for an (extended) pid.
145 */
146 SmallHashDynamic<PidKey, SessionKey> pid2session_;
147 pthread_mutex_t lock_pid2session_;
148 uint64_t deadline_sweep_pids_;
149
150 /**
151 * Caches credentials corresponding to a session.
152 */
153 SmallHashDynamic<SessionKey, AuthzData> session2cred_;
154 pthread_mutex_t lock_session2cred_;
155 uint64_t deadline_sweep_creds_;
156
157 /**
158 * The helper that takes care of bringing in credentials from the client
159 * context.
160 */
161 AuthzFetcher *authz_fetcher_;
162
163 perf::Counter *no_pid_;
164 perf::Counter *no_session_;
165 perf::Counter *n_fetch_;
166 perf::Counter *n_grant_;
167 perf::Counter *n_deny_;
168 };
169
170 #endif // CVMFS_AUTHZ_AUTHZ_SESSION_H_
171