GCC Code Coverage Report


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