mirror of
https://github.com/ceph/ceph
synced 2025-02-01 07:52:57 +00:00
auth: authorize stuff
This commit is contained in:
parent
cc9de15a55
commit
9c9404d9ea
@ -9,7 +9,7 @@ static void hexdump(string msg, const char *s, int len)
|
||||
int buf_len = len*4;
|
||||
char buf[buf_len];
|
||||
int pos = 0;
|
||||
for (unsigned int i=0; i<len && pos<buf_len - 8; i++) {
|
||||
for (int i=0; i<len && pos<buf_len - 8; i++) {
|
||||
if (i && !(i%8))
|
||||
pos += snprintf(&buf[pos], buf_len-pos, " ");
|
||||
if (i && !(i%16))
|
||||
@ -182,18 +182,34 @@ bool AuthTicketsManager::verify_service_ticket_reply(CryptoKey& secret,
|
||||
*
|
||||
* ticket, {timestamp, nonce}^session_key
|
||||
*/
|
||||
utime_t AuthTicketHandler::build_authenticator(bufferlist& bl)
|
||||
bool AuthTicketHandler::build_authorizer(bufferlist& bl, AuthorizeContext& ctx)
|
||||
{
|
||||
utime_t now = g_clock.now();
|
||||
ctx.timestamp = g_clock.now();
|
||||
|
||||
::encode(ticket, bl);
|
||||
|
||||
AuthAuthenticate msg;
|
||||
msg.now = now;
|
||||
AuthAuthorize msg;
|
||||
msg.trans_id = ctx.id;
|
||||
msg.now = ctx.timestamp;
|
||||
msg.nonce = nonce;
|
||||
encode_encrypt(msg, session_key, bl);
|
||||
|
||||
return now;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* PRINCIPAL: build authenticator to access the service.
|
||||
*
|
||||
* ticket, {timestamp, nonce}^session_key
|
||||
*/
|
||||
bool AuthTicketsManager::build_authorizer(uint32_t service_id, bufferlist& bl, AuthorizeContext& ctx)
|
||||
{
|
||||
map<uint32_t, AuthTicketHandler>::iterator iter = tickets_map.find(service_id);
|
||||
if (iter == tickets_map.end())
|
||||
return false;
|
||||
|
||||
AuthTicketHandler& handler = iter->second;
|
||||
return handler.build_authorizer(bl, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -201,13 +217,13 @@ utime_t AuthTicketHandler::build_authenticator(bufferlist& bl)
|
||||
*
|
||||
* {timestamp + 1}^session_key
|
||||
*/
|
||||
bool verify_authenticator(CryptoKey& service_secret, bufferlist::iterator& indata,
|
||||
bool verify_authorizer(CryptoKey& service_secret, bufferlist::iterator& indata,
|
||||
bufferlist& reply_bl)
|
||||
{
|
||||
AuthServiceTicketInfo ticket_info;
|
||||
decode_decrypt(ticket_info, service_secret, indata);
|
||||
|
||||
AuthAuthenticate auth_msg;
|
||||
AuthAuthorize auth_msg;
|
||||
decode_decrypt(auth_msg, ticket_info.session_key, indata);
|
||||
|
||||
// it's authentic if the nonces match
|
||||
@ -219,7 +235,8 @@ bool verify_authenticator(CryptoKey& service_secret, bufferlist::iterator& indat
|
||||
* Reply authenticator:
|
||||
* {timestamp + 1}^session_key
|
||||
*/
|
||||
AuthAuthenticateReply reply;
|
||||
AuthAuthorizeReply reply;
|
||||
reply.trans_id = auth_msg.trans_id;
|
||||
reply.timestamp = auth_msg.now;
|
||||
reply.timestamp += 1;
|
||||
encode_encrypt(reply, ticket_info.session_key, reply_bl);
|
||||
@ -232,17 +249,13 @@ bool verify_authenticator(CryptoKey& service_secret, bufferlist::iterator& indat
|
||||
/*
|
||||
* PRINCIPAL: verify reply is authentic
|
||||
*/
|
||||
bool AuthTicketHandler::verify_reply_authenticator(utime_t then, bufferlist& enc_reply)
|
||||
bool AuthTicketHandler::verify_reply_authorizer(utime_t then, bufferlist::iterator& indata)
|
||||
{
|
||||
bufferlist reply;
|
||||
if (session_key.decrypt(enc_reply, reply) < 0)
|
||||
AuthAuthorizeReply reply;
|
||||
if (decode_decrypt(reply, session_key, indata) < 0)
|
||||
return false;
|
||||
|
||||
bufferlist::iterator p = reply.begin();
|
||||
utime_t later;
|
||||
::decode(later, p);
|
||||
dout(0) << "later=" << later << " then=" << then << dendl;
|
||||
if (then + 1 == later) {
|
||||
|
||||
if (then + 1 == reply.timestamp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "Crypto.h"
|
||||
#include "msg/msg_types.h"
|
||||
|
||||
struct AuthorizeContext {
|
||||
int id;
|
||||
utime_t timestamp;
|
||||
};
|
||||
|
||||
struct EntityName {
|
||||
uint32_t entity_type;
|
||||
@ -145,8 +149,8 @@ struct AuthTicketHandler {
|
||||
bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl);
|
||||
#endif
|
||||
// to access the service
|
||||
utime_t build_authenticator(bufferlist& bl);
|
||||
bool verify_reply_authenticator(utime_t then, bufferlist& enc_reply);
|
||||
bool build_authorizer(bufferlist& bl, AuthorizeContext& ctx);
|
||||
bool verify_reply_authorizer(utime_t then, bufferlist::iterator& enc_reply);
|
||||
|
||||
bool has_key() { return has_key_flag; }
|
||||
};
|
||||
@ -160,6 +164,7 @@ struct AuthTicketsManager {
|
||||
bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl);
|
||||
|
||||
AuthTicketHandler& get_handler(uint32_t type) { return tickets_map[type]; }
|
||||
bool build_authorizer(uint32_t service_id, bufferlist& bl, AuthorizeContext& context);
|
||||
};
|
||||
|
||||
struct AuthServiceTicketRequest {
|
||||
@ -216,30 +221,36 @@ struct AuthServiceTicketInfo {
|
||||
};
|
||||
WRITE_CLASS_ENCODER(AuthServiceTicketInfo);
|
||||
|
||||
struct AuthAuthenticate {
|
||||
struct AuthAuthorize {
|
||||
uint32_t trans_id;
|
||||
utime_t now;
|
||||
string nonce;
|
||||
void encode(bufferlist& bl) const {
|
||||
::encode(trans_id, bl);
|
||||
::encode(now, bl);
|
||||
::encode(nonce, bl);
|
||||
}
|
||||
void decode(bufferlist::iterator& bl) {
|
||||
::decode(trans_id, bl);
|
||||
::decode(now, bl);
|
||||
::decode(nonce, bl);
|
||||
}
|
||||
};
|
||||
WRITE_CLASS_ENCODER(AuthAuthenticate);
|
||||
WRITE_CLASS_ENCODER(AuthAuthorize);
|
||||
|
||||
struct AuthAuthenticateReply {
|
||||
struct AuthAuthorizeReply {
|
||||
uint32_t trans_id;
|
||||
utime_t timestamp;
|
||||
void encode(bufferlist& bl) const {
|
||||
::encode(trans_id, bl);
|
||||
::encode(timestamp, bl);
|
||||
}
|
||||
void decode(bufferlist::iterator& bl) {
|
||||
::decode(trans_id, bl);
|
||||
::decode(timestamp, bl);
|
||||
}
|
||||
};
|
||||
WRITE_CLASS_ENCODER(AuthAuthenticateReply);
|
||||
WRITE_CLASS_ENCODER(AuthAuthorizeReply);
|
||||
|
||||
template <class T>
|
||||
int decode_decrypt(T& t, CryptoKey key, bufferlist::iterator& iter) {
|
||||
@ -282,7 +293,7 @@ extern bool build_authenticate_reply(AuthTicketHandler ticket_handler,
|
||||
CryptoKey& service_secret,
|
||||
bufferlist& reply);
|
||||
/*
|
||||
* Verify authenticator and generate reply authenticator
|
||||
* Verify authorizer and generate reply authorizer
|
||||
*/
|
||||
|
||||
extern bool verify_service_ticket_request(bool encrypted,
|
||||
@ -291,7 +302,7 @@ extern bool verify_service_ticket_request(bool encrypted,
|
||||
uint32_t& keys,
|
||||
bufferlist::iterator& indata);
|
||||
|
||||
extern bool verify_authenticator(CryptoKey& service_secret, bufferlist::iterator& bl,
|
||||
extern bool verify_authorizer(CryptoKey& service_secret, bufferlist::iterator& bl,
|
||||
bufferlist& enc_reply);
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "messages/MAuth.h"
|
||||
#include "messages/MAuthReply.h"
|
||||
|
||||
|
||||
int AuthClientHandler::generate_request(bufferlist& bl)
|
||||
{
|
||||
dout(0) << "status=" << status << dendl;
|
||||
@ -53,11 +52,11 @@ int AuthClientHandler::generate_request(bufferlist& bl)
|
||||
req.piggyback = 1;
|
||||
::encode(req, bl);
|
||||
request_state++;
|
||||
return generate_cephx_protocol_request(bl);
|
||||
return generate_cephx_authenticate_request(bl);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return generate_cephx_protocol_request(bl);
|
||||
return generate_cephx_authenticate_request(bl);
|
||||
}
|
||||
request_state++;
|
||||
return 0;
|
||||
@ -69,7 +68,7 @@ int AuthClientHandler::handle_response(Message *response)
|
||||
bufferlist bl;
|
||||
int ret;
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
char buf[4096];
|
||||
const char *s = bl.c_str();
|
||||
int pos = 0;
|
||||
@ -113,16 +112,16 @@ int AuthClientHandler::handle_response(Message *response)
|
||||
/* authenticate */
|
||||
{
|
||||
response_state++;
|
||||
return handle_cephx_protocol_response(iter);
|
||||
return handle_cephx_response(iter);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return handle_cephx_protocol_response(iter);
|
||||
return handle_cephx_response(iter);
|
||||
}
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
int AuthClientHandler::generate_cephx_protocol_request(bufferlist& bl)
|
||||
int AuthClientHandler::generate_cephx_authenticate_request(bufferlist& bl)
|
||||
{
|
||||
CephXRequestHeader header;
|
||||
AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
|
||||
@ -159,7 +158,26 @@ int AuthClientHandler::generate_cephx_protocol_request(bufferlist& bl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AuthClientHandler::handle_cephx_protocol_response(bufferlist::iterator& indata)
|
||||
int AuthClientHandler::generate_cephx_authorize_request(uint32_t service_id, bufferlist& bl)
|
||||
{
|
||||
CephXRequestHeader header;
|
||||
if (!(have & service_id)) {
|
||||
dout(0) << "can't authorize: missing service key" << dendl;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
header.request_type = CEPHX_OPEN_SESSION;
|
||||
|
||||
::encode(header, bl);
|
||||
AuthorizeContext& ctx = context_map.create();
|
||||
utime_t now;
|
||||
if (!tickets.build_authorizer(service_id, bl, ctx))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AuthClientHandler::handle_cephx_response(bufferlist::iterator& indata)
|
||||
{
|
||||
int ret = 0;
|
||||
struct CephXResponseHeader header;
|
||||
@ -204,8 +222,11 @@ int AuthClientHandler::handle_cephx_protocol_response(bufferlist::iterator& inda
|
||||
break;
|
||||
|
||||
case CEPHX_OPEN_SESSION:
|
||||
cephx_response_state = 3;
|
||||
dout(0) << "FIXME: CEPHX_OPEN_SESSION" << dendl;
|
||||
{
|
||||
AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
|
||||
utime_t then; /* FIXME */
|
||||
ticket_handler.verify_reply_authorizer(then, indata);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dout(0) << "header.request_type = " << hex << header.request_type << dec << dendl;
|
||||
@ -243,6 +264,15 @@ int AuthClientHandler::start_session(AuthClient *client, double timeout)
|
||||
return status;
|
||||
}
|
||||
|
||||
int AuthClientHandler::authorize(uint32_t service_id)
|
||||
{
|
||||
/* FIXME: do it via _do_request(), so that we get timeout handling */
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AuthClientHandler::tick()
|
||||
{
|
||||
Mutex::Locker l(lock);
|
||||
@ -323,3 +353,41 @@ void AuthClientHandler::handle_auth_reply(MAuthReply *m)
|
||||
cur_request_cond->Signal();
|
||||
}
|
||||
|
||||
/*
|
||||
class AuthorizeMap {
|
||||
map<int, AuthorizeContext> map;
|
||||
|
||||
Mutex lock;
|
||||
int max_id;
|
||||
|
||||
public:
|
||||
*/
|
||||
AuthorizeContext& AuthorizeContextMap::create()
|
||||
{
|
||||
Mutex::Locker l(lock);
|
||||
AuthorizeContext& ctx = m[max_id];
|
||||
ctx.id = max_id;
|
||||
++max_id;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void AuthorizeContextMap::remove(int id)
|
||||
{
|
||||
std::map<int, AuthorizeContext>::iterator iter = m.find(id);
|
||||
if (iter != m.end()) {
|
||||
m.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
AuthorizeContext *AuthorizeContextMap::get(int id)
|
||||
{
|
||||
Mutex::Locker l(lock);
|
||||
std::map<int, AuthorizeContext>::iterator iter = m.find(id);
|
||||
if (iter != m.end())
|
||||
return &iter->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,19 @@ class MAuthReply;
|
||||
class Message;
|
||||
class AuthClient;
|
||||
|
||||
class AuthorizeContextMap {
|
||||
map<int, AuthorizeContext> m;
|
||||
|
||||
Mutex lock;
|
||||
int max_id;
|
||||
|
||||
public:
|
||||
AuthorizeContextMap() : lock("AuthorizeMap") {}
|
||||
AuthorizeContext& create();
|
||||
void remove(int id);
|
||||
AuthorizeContext *get(int id);
|
||||
};
|
||||
|
||||
class AuthClientHandler {
|
||||
Mutex lock;
|
||||
Cond keys_cond;
|
||||
@ -63,13 +76,20 @@ class AuthClientHandler {
|
||||
|
||||
AuthClient *client;
|
||||
|
||||
AuthorizeContextMap context_map;
|
||||
|
||||
bool request_pending();
|
||||
Message *build_request();
|
||||
|
||||
int generate_request(bufferlist& bl);
|
||||
int handle_response(Message *response);
|
||||
int generate_cephx_protocol_request(bufferlist& bl);
|
||||
int handle_cephx_protocol_response(bufferlist::iterator& indata);
|
||||
|
||||
/* cephx requests */
|
||||
int generate_cephx_authenticate_request(bufferlist& bl);
|
||||
int generate_cephx_authorize_request(uint32_t service_id, bufferlist& bl);
|
||||
|
||||
/* cephx responses */
|
||||
int handle_cephx_response(bufferlist::iterator& indata);
|
||||
|
||||
void _reset() {
|
||||
request_state = 0;
|
||||
@ -129,6 +149,7 @@ public:
|
||||
}
|
||||
|
||||
int start_session(AuthClient *client, double timeout);
|
||||
int authorize(uint32_t service_id);
|
||||
void handle_auth_reply(MAuthReply *m);
|
||||
void tick();
|
||||
};
|
||||
|
@ -166,8 +166,11 @@ WRITE_CLASS_ENCODER(CephXEnvRequest2);
|
||||
|
||||
#define CEPHX_PRINCIPAL_TYPE_MASK 0x00FF
|
||||
|
||||
/* authenticate requests */
|
||||
#define CEPHX_GET_AUTH_SESSION_KEY 0x0100
|
||||
#define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200
|
||||
|
||||
/* authorize requests */
|
||||
#define CEPHX_OPEN_SESSION 0x0300
|
||||
|
||||
#define CEPHX_REQUEST_TYPE_MASK 0x0F00
|
||||
|
@ -303,10 +303,10 @@ bool RadosClient::init()
|
||||
return false;
|
||||
|
||||
monclient.init();
|
||||
monclient.mount(g_conf.client_mount_timeout);
|
||||
dout(0) << "librados: before monclient.authorize()" << dendl;
|
||||
dout(0) << "librados: before monclient.authenticate()" << dendl;
|
||||
monclient.auth.set_want_keys(CEPHX_PRINCIPAL_MON | CEPHX_PRINCIPAL_OSD);
|
||||
monclient.authorize(g_conf.client_mount_timeout);
|
||||
monclient.authenticate(g_conf.client_mount_timeout);
|
||||
monclient.mount(g_conf.client_mount_timeout);
|
||||
|
||||
lock.Lock();
|
||||
|
||||
|
@ -261,7 +261,7 @@ void MonClient::handle_mount_ack(MClientMountAck* m)
|
||||
delete m;
|
||||
}
|
||||
|
||||
int MonClient::authorize(double timeout)
|
||||
int MonClient::authenticate(double timeout)
|
||||
{
|
||||
Mutex::Locker lock(monc_lock);
|
||||
|
||||
@ -297,10 +297,10 @@ void MonClient::ms_handle_reset(const entity_addr_t& peer)
|
||||
dout(0) << "staring hunt for new mon" << dendl;
|
||||
hunting = true;
|
||||
_pick_new_mon();
|
||||
auth.start_session(this, 30.0);
|
||||
if (mounting)
|
||||
_send_mount();
|
||||
_renew_subs();
|
||||
auth.start_session(this, 30.0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,3 +369,8 @@ void MonClient::handle_subscribe_ack(MMonSubscribeAck *m)
|
||||
delete m;
|
||||
}
|
||||
|
||||
int MonClient::authorize()
|
||||
{
|
||||
return auth.authorize(CEPHX_PRINCIPAL_MON);
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,8 @@ private:
|
||||
|
||||
public:
|
||||
int mount(double mount_timeout);
|
||||
int authorize(double timeout);
|
||||
int authenticate(double timeout);
|
||||
int authorize();
|
||||
|
||||
// mon subscriptions
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user