GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/authz/authz_fetch.h
Date: 2026-03-15 02:35:27
Exec Total Coverage
Lines: 3 3 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_AUTHZ_AUTHZ_FETCH_H_
6 #define CVMFS_AUTHZ_AUTHZ_FETCH_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 "json_document.h"
17 #include "util/single_copy.h"
18
19 class OptionsManager;
20
21 class AuthzFetcher {
22 public:
23 struct QueryInfo {
24 294 QueryInfo(pid_t p, uid_t u, gid_t g, const std::string &m)
25 294 : pid(p), uid(u), gid(g), membership(m) { }
26 pid_t pid;
27 uid_t uid;
28 gid_t gid;
29 std::string membership;
30 };
31
32 4760 virtual ~AuthzFetcher() { }
33
34 /**
35 * Based on the given pid, uid, gid and the given membership requirement,
36 * gather credentials. Positive and negative replies have a time to live.
37 */
38 virtual AuthzStatus Fetch(const QueryInfo &query_info,
39 AuthzToken *authz_token,
40 unsigned *ttl) = 0;
41
42 /*
43 * Once membership is known, see if the helper process needs to be
44 * launched. Run from a privileged thread.
45 */
46 virtual AuthzStatus CheckHelper(const std::string &membership) = 0;
47 };
48
49
50 /**
51 * Defines the result on construction. Used in libcvmfs and for testing.
52 */
53 class AuthzStaticFetcher : public AuthzFetcher {
54 public:
55 AuthzStaticFetcher(AuthzStatus s, unsigned ttl) : status_(s), ttl_(ttl) { }
56 virtual ~AuthzStaticFetcher() { }
57 virtual AuthzStatus Fetch(const QueryInfo &query_info,
58 AuthzToken *authz_token,
59 unsigned *ttl) {
60 *authz_token = AuthzToken();
61 *ttl = ttl_;
62 return status_;
63 }
64
65 virtual AuthzStatus CheckHelper(const std::string &membership)
66 {
67 return kAuthzOk;
68 }
69
70 private:
71 AuthzStatus status_;
72 unsigned ttl_;
73 };
74
75
76 /**
77 * Types of messages that can be sent between cvmfs client and authz helper.
78 */
79 enum AuthzExternalMsgIds {
80 kAuthzMsgHandshake = 0, ///< Cvmfs: "Hello, helper, are you there?"
81 kAuthzMsgReady, ///< Helper: "Yes, cvmfs, I'm here"
82 kAuthzMsgVerify, ///< Cvmfs: "Please verify, helper"
83 kAuthzMsgPermit, ///< Helper: "I verified, cvmfs, here's the result"
84 kAuthzMsgQuit, ///< Cvmfs: "Please shutdown, helper"
85 kAuthzMsgInvalid ///< First invalid message id
86 };
87
88
89 /**
90 * A binary representation of JSON messages that can be received from an authz
91 * helper. Holds either a kAuthzMsgReady or a kAuthzMsgPermit message.
92 */
93 struct AuthzExternalMsg {
94 AuthzExternalMsgIds msgid;
95 int protocol_revision;
96 struct {
97 AuthzStatus status;
98 AuthzToken token;
99 uint32_t ttl;
100 } permit;
101 };
102
103
104 /**
105 * Connects to an external process that fetches the tokens. The external helper
106 * is spawned on demand through execve. It has to receive commands on stdin
107 * and write replies to stdout. Environment variables of the form
108 * CVMFS_AUTHZ_... are forwarded to the helper having the CVMFS_AUTHZ_ prefix
109 * stripped.
110 */
111 class AuthzExternalFetcher : public AuthzFetcher, SingleCopy {
112 FRIEND_TEST(T_AuthzFetch, ExecHelper);
113 FRIEND_TEST(T_AuthzFetch, ExecHelperSlow);
114 FRIEND_TEST(T_AuthzFetch, ParseMsg);
115 FRIEND_TEST(T_AuthzFetch, Handshake);
116
117 public:
118 /**
119 * The "wire" protocol: 4 byte version, 4 byte length, JSON message. Must
120 * be the same for cvmfs and helper.
121 */
122 static const uint32_t kProtocolVersion; // = 1;
123
124 AuthzExternalFetcher(const std::string &fqrn,
125 const std::string &progname,
126 const std::string &search_path,
127 OptionsManager *options_manager);
128 AuthzExternalFetcher(const std::string &fqrn, int fd_send, int fd_recv);
129 virtual ~AuthzExternalFetcher();
130
131 virtual AuthzStatus Fetch(const QueryInfo &query_info,
132 AuthzToken *authz_token,
133 unsigned *ttl);
134
135 virtual AuthzStatus CheckHelper(const std::string &membership);
136
137 private:
138 /**
139 * After 5 seconds of unresponsiveness, helper processes may be killed.
140 */
141 static const unsigned kChildTimeout = 5;
142
143 /**
144 * For now we allow "no caching".
145 */
146 static const int kMinTtl; // = 0
147
148 /**
149 * If permits come without TTL, use 2 minutes.
150 */
151 static const unsigned kDefaultTtl = 120;
152
153 void InitLock();
154 std::string FindHelper(const std::string &membership);
155 void ExecHelper();
156 bool Handshake();
157
158 bool Send(const std::string &msg);
159 bool Recv(std::string *msg);
160 void EnterFailState();
161
162 void StripAuthzSchema(const std::string &membership,
163 std::string *authz_schema,
164 std::string *pure_membership);
165 bool ParseMsg(const std::string &json_msg,
166 const AuthzExternalMsgIds expected_msgid,
167 AuthzExternalMsg *binary_msg);
168 bool ParseMsgId(JSON *json_authz, AuthzExternalMsg *binary_msg);
169 bool ParseRevision(JSON *json_authz, AuthzExternalMsg *binary_msg);
170 bool ParsePermit(JSON *json_authz, AuthzExternalMsg *binary_msg);
171
172 void ReapHelper();
173
174 /**
175 * The fully qualified repository name, e.g. atlas.cern.ch
176 */
177 std::string fqrn_;
178
179 /**
180 * Full path of external helper.
181 */
182 std::string progname_;
183
184 /**
185 * Where to look for authz helpers that are guessed from the membership schema
186 */
187 std::string search_path_;
188
189 /**
190 * Send requests to the external helper.
191 */
192 int fd_send_;
193
194 /**
195 * Receive authz status, ttl, and token from the external helper.
196 */
197 int fd_recv_;
198
199 /**
200 * If a helper was started, the pid must be collected to avoid a zombie.
201 */
202 pid_t pid_;
203
204 /**
205 * If the external helper behaves unexectely, enter fail state and stop
206 * authenticating
207 */
208 bool fail_state_;
209
210 /**
211 * Used to gather CVMFS_AUTHZ_ options
212 */
213 OptionsManager *options_manager_;
214
215 /**
216 * The send-receive cycle is atomic.
217 */
218 pthread_mutex_t lock_;
219
220 /**
221 * After the helper process fails, this is set to the time when it should
222 * be restarted.
223 */
224 uint64_t next_start_;
225 };
226
227 #endif // CVMFS_AUTHZ_AUTHZ_FETCH_H_
228