1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
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.
15 #ifndef CEPH_AUTHTYPES_H
16 #define CEPH_AUTHTYPES_H
19 #include "common/entity_name.h"
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
27 AUTH_MODE_AUTHORIZER
= 1,
28 AUTH_MODE_AUTHORIZER_MAX
= 9,
30 AUTH_MODE_MON_MAX
= 19,
36 std::map
<std::string
, ceph::buffer::list
> caps
;
38 void encode(ceph::buffer::list
& bl
) const {
42 encode((uint64_t)CEPH_AUTH_UID_DEFAULT
, bl
);
46 void decode(ceph::buffer::list::const_iterator
& bl
) {
58 WRITE_CLASS_ENCODER(EntityAuth
)
60 inline std::ostream
& operator<<(std::ostream
& out
, const EntityAuth
& a
) {
61 return out
<< "auth(key=" << a
.key
<< ")";
66 ceph::buffer::list caps
;
68 AuthCapsInfo() : allow_all(false) {}
70 void encode(ceph::buffer::list
& bl
) const {
74 __u8 a
= (__u8
)allow_all
;
78 void decode(ceph::buffer::list::const_iterator
& bl
) {
88 WRITE_CLASS_ENCODER(AuthCapsInfo
)
91 * The ticket (if properly validated) authorizes the principal use
92 * services as described by 'caps' during the specified validity
97 uint64_t global_id
; /* global instance id */
98 utime_t created
, renew_after
, expires
;
102 AuthTicket() : global_id(0), flags(0){}
104 void init_timestamps(utime_t now
, double ttl
) {
109 renew_after
+= ttl
/ 2.0;
112 void encode(ceph::buffer::list
& bl
) const {
115 encode(struct_v
, bl
);
117 encode(global_id
, bl
);
118 encode((uint64_t)CEPH_AUTH_UID_DEFAULT
, bl
);
124 void decode(ceph::buffer::list::const_iterator
& bl
) {
127 decode(struct_v
, bl
);
129 decode(global_id
, bl
);
132 decode(old_auid
, bl
);
140 WRITE_CLASS_ENCODER(AuthTicket
)
144 * abstract authorizer class
146 struct AuthAuthorizer
{
148 ceph::buffer::list bl
;
149 CryptoKey session_key
;
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;
159 struct AuthAuthorizerChallenge
{
160 virtual ~AuthAuthorizerChallenge() {}
163 struct AuthConnectionMeta
{
164 uint32_t auth_method
= CEPH_AUTH_UNKNOWN
; //< CEPH_AUTH_*
166 /// client: initial empty, but populated if server said bad method
167 std::vector
<uint32_t> allowed_methods
;
169 int auth_mode
= AUTH_MODE_NONE
; ///< AUTH_MODE_*
171 int con_mode
= 0; ///< negotiated mode
173 bool is_mode_crc() const {
174 return con_mode
== CEPH_CON_MODE_CRC
;
176 bool is_mode_secure() const {
177 return con_mode
== CEPH_CON_MODE_SECURE
;
180 CryptoKey session_key
; ///< per-ticket key
182 size_t get_connection_secret_length() const {
184 case CEPH_CON_MODE_CRC
:
186 case CEPH_CON_MODE_SECURE
:
191 std::string connection_secret
; ///< per-connection key
193 std::unique_ptr
<AuthAuthorizer
> authorizer
;
194 std::unique_ptr
<AuthAuthorizerChallenge
> authorizer_challenge
;
196 ///< set if msgr1 peer doesn't support CEPHX_V2
197 bool skip_authorizer_challenge
= false;
203 #define KEY_ROTATE_NUM 3 /* prev, current, next */
205 struct ExpiringCryptoKey
{
209 void encode(ceph::buffer::list
& bl
) const {
212 encode(struct_v
, bl
);
214 encode(expiration
, bl
);
216 void decode(ceph::buffer::list::const_iterator
& bl
) {
219 decode(struct_v
, bl
);
221 decode(expiration
, bl
);
224 WRITE_CLASS_ENCODER(ExpiringCryptoKey
)
226 inline std::ostream
& operator<<(std::ostream
& out
, const ExpiringCryptoKey
& c
)
228 return out
<< c
.key
<< " expires " << c
.expiration
;
231 struct RotatingSecrets
{
232 std::map
<uint64_t, ExpiringCryptoKey
> secrets
;
235 RotatingSecrets() : max_ver(0) {}
237 void encode(ceph::buffer::list
& bl
) const {
240 encode(struct_v
, bl
);
244 void decode(ceph::buffer::list::const_iterator
& bl
) {
247 decode(struct_v
, bl
);
252 uint64_t add(ExpiringCryptoKey
& key
) {
253 secrets
[++max_ver
] = key
;
254 while (secrets
.size() > KEY_ROTATE_NUM
)
255 secrets
.erase(secrets
.begin());
259 bool need_new_secrets() const {
260 return secrets
.size() < KEY_ROTATE_NUM
;
262 bool need_new_secrets(const utime_t
& now
) const {
263 return secrets
.size() < KEY_ROTATE_NUM
|| current().expiration
<= now
;
266 ExpiringCryptoKey
& previous() {
267 return secrets
.begin()->second
;
269 ExpiringCryptoKey
& current() {
270 auto p
= secrets
.begin();
274 const ExpiringCryptoKey
& current() const {
275 auto p
= secrets
.begin();
279 ExpiringCryptoKey
& next() {
280 return secrets
.rbegin()->second
;
283 return secrets
.empty();
288 WRITE_CLASS_ENCODER(RotatingSecrets
)
294 virtual ~KeyStore() {}
295 virtual bool get_secret(const EntityName
& name
, CryptoKey
& secret
) const = 0;
296 virtual bool get_service_secret(uint32_t service_id
, uint64_t secret_id
,
297 CryptoKey
& secret
) const = 0;
300 inline bool auth_principal_needs_rotating_keys(EntityName
& name
)
302 uint32_t ty(name
.get_type());
303 return ((ty
== CEPH_ENTITY_TYPE_OSD
)
304 || (ty
== CEPH_ENTITY_TYPE_MDS
)
305 || (ty
== CEPH_ENTITY_TYPE_MGR
));