auth: authorize stuff

This commit is contained in:
Yehuda Sadeh 2009-09-11 13:43:28 -07:00
parent cc9de15a55
commit 9c9404d9ea
8 changed files with 166 additions and 44 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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();
};

View File

@ -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

View File

@ -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();

View File

@ -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);
}

View File

@ -77,7 +77,8 @@ private:
public:
int mount(double mount_timeout);
int authorize(double timeout);
int authenticate(double timeout);
int authorize();
// mon subscriptions
private: