GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/authz/authz_session.h Lines: 20 20 100.0 %
Date: 2019-02-03 02:48:13 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 "murmur.h"
17
#include "smallhash.h"
18
#include "statistics.h"
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
1785
  struct PidKey {
73
2051
    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
604
    bool operator ==(const PidKey &other) const {
82
      return (pid == other.pid) &&
83

604
             (pid_bday == other.pid_bday);
84
    }
85
86
504
    bool operator !=(const PidKey &other) const {
87
504
      return !(*this == other);
88
    }
89
  };
90
91
  /**
92
   * Extended information on an SID.
93
   */
94
3654
  struct SessionKey {
95
3977
    SessionKey() : sid(-1), sid_bday(0) { }
96
    pid_t sid;
97
    uint64_t sid_bday;
98
99
2369
    bool operator ==(const SessionKey &other) const {
100
      return (sid == other.sid) &&
101

2369
             (sid_bday == other.sid_bday);
102
    }
103
104
2205
    bool operator !=(const SessionKey &other) const {
105
2205
      return !(*this == other);
106
    }
107
  };
108
109
72
  static uint32_t HashPidKey(const PidKey &key) {
110
    struct {
111
      uint64_t bday;
112
      pid_t pid;
113
    }  __attribute__((packed)) key_info;
114
72
    key_info.pid = key.pid;
115
72
    key_info.bday = key.pid_bday;
116
72
    return MurmurHash2(&key_info, sizeof(key_info), 0x07387a4f);
117
  }
118
119
120
  static uint32_t HashSessionKey(const SessionKey &key) {
120
    struct {
121
      uint64_t bday;
122
      pid_t pid;
123
    } __attribute__((packed)) key_info;
124
120
    key_info.pid = key.sid;
125
120
    key_info.bday = key.sid_bday;
126
120
    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_