1    	// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2    	// vim: ts=8 sw=2 smarttab
3    	/*
4    	 * Ceph - scalable distributed file system
5    	 *
6    	 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
7    	 *
8    	 * This is free software; you can redistribute it and/or
9    	 * modify it under the terms of the GNU Lesser General Public
10   	 * License version 2.1, as published by the Free Software 
11   	 * Foundation.  See file COPYING.
12   	 * 
13   	 */
14   	
15   	#ifndef CEPH_AUTHTYPES_H
16   	#define CEPH_AUTHTYPES_H
17   	
18   	#include "Crypto.h"
19   	#include "common/entity_name.h"
20   	
21   	// The _MAX values are a bit wonky here because we are overloading the first
22   	// byte of the auth payload to identify both the type of authentication to be
23   	// used *and* the encoding version for the authenticator.  So, we define a
24   	// range.
25   	enum {
26   	  AUTH_MODE_NONE = 0,
27   	  AUTH_MODE_AUTHORIZER = 1,
28   	  AUTH_MODE_AUTHORIZER_MAX = 9,
29   	  AUTH_MODE_MON = 10,
30   	  AUTH_MODE_MON_MAX = 19,
31   	};
32   	
33   	
34   	struct EntityAuth {
35   	  CryptoKey key;
36   	  std::map<std::string, ceph::buffer::list> caps;
37   	
38   	  void encode(ceph::buffer::list& bl) const {
39   	    __u8 struct_v = 2;
40   	    using ceph::encode;
41   	    encode(struct_v, bl);
42   	    encode((uint64_t)CEPH_AUTH_UID_DEFAULT, bl);
43   	    encode(key, bl);
44   	    encode(caps, bl);
45   	  }
46   	  void decode(ceph::buffer::list::const_iterator& bl) {
47   	    using ceph::decode;
48   	    __u8 struct_v;
49   	    decode(struct_v, bl);
50   	    if (struct_v >= 2) {
51   	      uint64_t old_auid;
52   	      decode(old_auid, bl);
53   	    }
54   	    decode(key, bl);
55   	    decode(caps, bl);
56   	  }
57   	};
58   	WRITE_CLASS_ENCODER(EntityAuth)
59   	
60   	inline std::ostream& operator<<(std::ostream& out, const EntityAuth& a) {
61   	  return out << "auth(key=" << a.key << ")";
62   	}
63   	
64   	struct AuthCapsInfo {
65   	  bool allow_all;
66   	  ceph::buffer::list caps;
67   	
68   	  AuthCapsInfo() : allow_all(false) {}
69   	
70   	  void encode(ceph::buffer::list& bl) const {
71   	    using ceph::encode;
(1) Event assignment: Assigning: "struct_v" = "1".
Also see events: [overrun-buffer-val]
72   	    __u8 struct_v = 1;
(2) Event overrun-buffer-val: Overrunning buffer pointed to by "struct_v" of 1 bytes by passing it to a function which accesses it at byte offset 7. [details]
Also see events: [assignment]
73   	    encode(struct_v, bl);
74   	    __u8 a = (__u8)allow_all;
75   	    encode(a, bl);
76   	    encode(caps, bl);
77   	  }
78   	  void decode(ceph::buffer::list::const_iterator& bl) {
79   	    using ceph::decode;
80   	    __u8 struct_v;
81   	    decode(struct_v, bl);
82   	    __u8 a;
83   	    decode(a, bl);
84   	    allow_all = (bool)a;
85   	    decode(caps, bl);
86   	  }
87   	};
88   	WRITE_CLASS_ENCODER(AuthCapsInfo)
89   	
90   	/*
91   	 * The ticket (if properly validated) authorizes the principal use
92   	 * services as described by 'caps' during the specified validity
93   	 * period.
94   	 */
95   	struct AuthTicket {
96   	  EntityName name;
97   	  uint64_t global_id; /* global instance id */
98   	  utime_t created, renew_after, expires;
99   	  AuthCapsInfo caps;
100  	  __u32 flags;
101  	
102  	  AuthTicket() : global_id(0), flags(0){}
103  	
104  	  void init_timestamps(utime_t now, double ttl) {
105  	    created = now;
106  	    expires = now;
107  	    expires += ttl;
108  	    renew_after = now;
109  	    renew_after += ttl / 2.0;
110  	  }
111  	
112  	  void encode(ceph::buffer::list& bl) const {
113  	    using ceph::encode;
114  	    __u8 struct_v = 2;
115  	    encode(struct_v, bl);
116  	    encode(name, bl);
117  	    encode(global_id, bl);
118  	    encode((uint64_t)CEPH_AUTH_UID_DEFAULT, bl);
119  	    encode(created, bl);
120  	    encode(expires, bl);
121  	    encode(caps, bl);
122  	    encode(flags, bl);
123  	  }
124  	  void decode(ceph::buffer::list::const_iterator& bl) {
125  	    using ceph::decode;
126  	    __u8 struct_v;
127  	    decode(struct_v, bl);
128  	    decode(name, bl);
129  	    decode(global_id, bl);
130  	    if (struct_v >= 2) {
131  	      uint64_t old_auid;
132  	      decode(old_auid, bl);
133  	    }
134  	    decode(created, bl);
135  	    decode(expires, bl);
136  	    decode(caps, bl);
137  	    decode(flags, bl);
138  	  }
139  	};
140  	WRITE_CLASS_ENCODER(AuthTicket)
141  	
142  	
143  	/*
144  	 * abstract authorizer class
145  	 */
146  	struct AuthAuthorizer {
147  	  __u32 protocol;
148  	  ceph::buffer::list bl;
149  	  CryptoKey session_key;
150  	
151  	  explicit AuthAuthorizer(__u32 p) : protocol(p) {}
152  	  virtual ~AuthAuthorizer() {}
153  	  virtual bool verify_reply(ceph::buffer::list::const_iterator& reply,
154  				    std::string *connection_secret) = 0;
155  	  virtual bool add_challenge(CephContext *cct,
156  				     const ceph::buffer::list& challenge) = 0;
157  	};
158  	
159  	struct AuthAuthorizerChallenge {
160  	  virtual ~AuthAuthorizerChallenge() {}
161  	};
162  	
163  	struct AuthConnectionMeta {
164  	  uint32_t auth_method = CEPH_AUTH_UNKNOWN;  //< CEPH_AUTH_*
165  	
166  	  /// client: initial empty, but populated if server said bad method
167  	  std::vector<uint32_t> allowed_methods;
168  	
169  	  int auth_mode = AUTH_MODE_NONE;  ///< AUTH_MODE_*
170  	
171  	  int con_mode = 0;  ///< negotiated mode
172  	
173  	  bool is_mode_crc() const {
174  	    return con_mode == CEPH_CON_MODE_CRC;
175  	  }
176  	  bool is_mode_secure() const {
177  	    return con_mode == CEPH_CON_MODE_SECURE;
178  	  }
179  	
180  	  CryptoKey session_key;           ///< per-ticket key
181  	
182  	  size_t get_connection_secret_length() const {
183  	    switch (con_mode) {
184  	    case CEPH_CON_MODE_CRC:
185  	      return 0;
186  	    case CEPH_CON_MODE_SECURE:
187  	      return 16 * 4;
188  	    }
189  	    return 0;
190  	  }
191  	  std::string connection_secret;   ///< per-connection key
192  	
193  	  std::unique_ptr<AuthAuthorizer> authorizer;
194  	  std::unique_ptr<AuthAuthorizerChallenge> authorizer_challenge;
195  	};
196  	
197  	/*
198  	 * Key management
199  	 */ 
200  	#define KEY_ROTATE_NUM 3   /* prev, current, next */
201  	
202  	struct ExpiringCryptoKey {
203  	  CryptoKey key;
204  	  utime_t expiration;
205  	
206  	  void encode(ceph::buffer::list& bl) const {
207  	    using ceph::encode;
208  	    __u8 struct_v = 1;
209  	    encode(struct_v, bl);
210  	    encode(key, bl);
211  	    encode(expiration, bl);
212  	  }
213  	  void decode(ceph::buffer::list::const_iterator& bl) {
214  	    using ceph::decode;
215  	    __u8 struct_v;
216  	    decode(struct_v, bl);
217  	    decode(key, bl);
218  	    decode(expiration, bl);
219  	  }
220  	};
221  	WRITE_CLASS_ENCODER(ExpiringCryptoKey)
222  	
223  	inline std::ostream& operator<<(std::ostream& out, const ExpiringCryptoKey& c)
224  	{
225  	  return out << c.key << " expires " << c.expiration;
226  	}
227  	
228  	struct RotatingSecrets {
229  	  std::map<uint64_t, ExpiringCryptoKey> secrets;
230  	  version_t max_ver;
231  	
232  	  RotatingSecrets() : max_ver(0) {}
233  	
234  	  void encode(ceph::buffer::list& bl) const {
235  	    using ceph::encode;
236  	    __u8 struct_v = 1;
237  	    encode(struct_v, bl);
238  	    encode(secrets, bl);
239  	    encode(max_ver, bl);
240  	  }
241  	  void decode(ceph::buffer::list::const_iterator& bl) {
242  	    using ceph::decode;
243  	    __u8 struct_v;
244  	    decode(struct_v, bl);
245  	    decode(secrets, bl);
246  	    decode(max_ver, bl);
247  	  }
248  	  
249  	  uint64_t add(ExpiringCryptoKey& key) {
250  	    secrets[++max_ver] = key;
251  	    while (secrets.size() > KEY_ROTATE_NUM)
252  	      secrets.erase(secrets.begin());
253  	    return max_ver;
254  	  }
255  	  
256  	  bool need_new_secrets() const {
257  	    return secrets.size() < KEY_ROTATE_NUM;
258  	  }
259  	  bool need_new_secrets(const utime_t& now) const {
260  	    return secrets.size() < KEY_ROTATE_NUM || current().expiration <= now;
261  	  }
262  	
263  	  ExpiringCryptoKey& previous() {
264  	    return secrets.begin()->second;
265  	  }
266  	  ExpiringCryptoKey& current() {
267  	    auto p = secrets.begin();
268  	    ++p;
269  	    return p->second;
270  	  }
271  	  const ExpiringCryptoKey& current() const {
272  	    auto p = secrets.begin();
273  	    ++p;
274  	    return p->second;
275  	  }
276  	  ExpiringCryptoKey& next() {
277  	    return secrets.rbegin()->second;
278  	  }
279  	  bool empty() {
280  	    return secrets.empty();
281  	  }
282  	
283  	  void dump();
284  	};
285  	WRITE_CLASS_ENCODER(RotatingSecrets)
286  	
287  	
288  	
289  	class KeyStore {
290  	public:
291  	  virtual ~KeyStore() {}
292  	  virtual bool get_secret(const EntityName& name, CryptoKey& secret) const = 0;
293  	  virtual bool get_service_secret(uint32_t service_id, uint64_t secret_id,
294  					  CryptoKey& secret) const = 0;
295  	};
296  	
297  	inline bool auth_principal_needs_rotating_keys(EntityName& name)
298  	{
299  	  uint32_t ty(name.get_type());
300  	  return ((ty == CEPH_ENTITY_TYPE_OSD)
301  	      || (ty == CEPH_ENTITY_TYPE_MDS)
302  	      || (ty == CEPH_ENTITY_TYPE_MGR));
303  	}
304  	
305  	#endif
306