GCC Code Coverage Report


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