GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/authz/authz_fetch.h Lines: 7 7 100.0 %
Date: 2019-02-03 02:48:13 Branches: 1 2 50.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
235
class AuthzFetcher {
22
 public:
23
43
  struct QueryInfo {
24
43
    QueryInfo(pid_t p, uid_t u, gid_t g, const std::string &m)
25
43
      : 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
235
  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
45
struct AuthzExternalMsg {
84
  AuthzExternalMsgIds msgid;
85
  int protocol_revision;
86
45
  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 prcesses 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_