From f23c5abb7a29ac1490f39c8dedc63bcfaf79c8eb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 23 Oct 2009 11:39:12 -0700 Subject: [PATCH] auth: move cephx server side into cephx dir --- src/Makefile.am | 2 + src/auth/AuthServiceHandler.cc | 189 +------------------------- src/auth/AuthServiceHandler.h | 11 +- src/auth/cephx/CephxServiceHandler.cc | 178 ++++++++++++++++++++++++ src/auth/cephx/CephxServiceHandler.h | 39 ++++++ src/mon/AuthMonitor.cc | 2 +- 6 files changed, 226 insertions(+), 195 deletions(-) create mode 100644 src/auth/cephx/CephxServiceHandler.cc create mode 100644 src/auth/cephx/CephxServiceHandler.h diff --git a/src/Makefile.am b/src/Makefile.am index fe4ff75748297..0cafae0584383 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -333,6 +333,7 @@ libcrush_a_SOURCES = \ crush/crush.c libmon_a_SOURCES = \ + auth/cephx/CephxServiceHandler.cc \ auth/AuthServiceHandler.cc \ mon/Monitor.cc \ mon/Paxos.cc \ @@ -401,6 +402,7 @@ libclient_a_SOURCES = \ noinst_HEADERS = \ auth/cephx/CephxProtocol.h\ auth/cephx/CephxClientHandler.h\ + auth/cephx/CephxServiceHandler.h\ auth/Auth.h\ auth/AuthServiceHandler.h\ auth/KeyRing.h\ diff --git a/src/auth/AuthServiceHandler.cc b/src/auth/AuthServiceHandler.cc index 94d10171a697e..dbfb5897b3558 100644 --- a/src/auth/AuthServiceHandler.cc +++ b/src/auth/AuthServiceHandler.cc @@ -12,196 +12,13 @@ * */ - #include "AuthServiceHandler.h" -#include "cephx/CephxProtocol.h" -#include "Auth.h" - -#include "mon/Monitor.h" - -#include -#include - -#include "config.h" - -/* - the first X request is empty, we then send a response and get another request which - is not empty and contains the client challenge and the key -*/ -class CephAuthService_X : public AuthServiceHandler { - int state; - uint64_t server_challenge; - EntityName entity_name; - -public: - CephAuthService_X(Monitor *m) : AuthServiceHandler(m), state(0) {} - ~CephAuthService_X() {} - - int start_session(bufferlist& result_bl); - int handle_request(bufferlist::iterator& indata, bufferlist& result_bl); - int handle_cephx_protocol(bufferlist::iterator& indata, bufferlist& result_bl); - void build_cephx_response_header(int request_type, int status, bufferlist& bl); -}; - - -int CephAuthService_X::start_session(bufferlist& result_bl) -{ - CephXEnvResponse1 response; - get_random_bytes((char *)&server_challenge, sizeof(server_challenge)); - response.server_challenge = server_challenge; - ::encode(response, result_bl); - state = 1; - return CEPH_AUTH_CEPHX; -} - -int CephAuthService_X::handle_request(bufferlist::iterator& indata, bufferlist& result_bl) -{ - int ret = 0; - - dout(0) << "CephAuthService_X: handle request" << dendl; - dout(0) << "state=" << state << dendl; - - switch (state) { - case 0: - assert(0); - break; - case 1: - { - CephXGetMonKey req; - ::decode(req, indata); - - entity_name = req.name; - - CryptoKey secret; - dout(0) << "entity_name=" << entity_name.to_str() << dendl; - if (!mon->key_server.get_secret(entity_name, secret)) { - dout(0) << "couldn't find entity name: " << entity_name.to_str() << dendl; - ret = -EPERM; - break; - } - - bufferlist key, key_enc; - ::encode(server_challenge, key); - ::encode(req.client_challenge, key); - ret = encode_encrypt(key, secret, key_enc); - if (ret < 0) - break; - uint64_t expected_key = 0; - const uint64_t *p = (const uint64_t *)key_enc.c_str(); - for (int pos = 0; pos + sizeof(req.key) <= key_enc.length(); pos+=sizeof(req.key), p++) { - expected_key ^= *p; - } - dout(0) << "checking key: req.key=" << hex << req.key << " expected_key=" << expected_key << dec << dendl; - if (req.key != expected_key) { - dout(0) << "unexpected key: req.key=" << req.key << " expected_key=" << expected_key << dendl; - ret = -EPERM; - break; - } - - dout(0) << "CEPHX_GET_AUTH_SESSION_KEY" << dendl; - struct CephXRequestHeader cephx_header; - ::decode(cephx_header, indata); - - AuthAuthenticateRequest areq; - ::decode(areq, indata); - - CryptoKey session_key; - SessionAuthInfo info; - - CryptoKey principal_secret; - if (mon->key_server.get_secret(areq.name, principal_secret) < 0) { - ret = -EPERM; - break; - } - - info.ticket.name = areq.name; - info.ticket.init_timestamps(g_clock.now(), g_conf.auth_mon_ticket_ttl); - - mon->key_server.generate_secret(session_key); - - info.session_key = session_key; - info.service_id = CEPH_ENTITY_TYPE_AUTH; - if (!mon->key_server.get_service_secret(CEPH_ENTITY_TYPE_AUTH, info.service_secret, info.secret_id)) { - dout(0) << "could not get service secret for auth subsystem" << dendl; - ret = -EIO; - break; - } - - vector info_vec; - info_vec.push_back(info); - - build_cephx_response_header(cephx_header.request_type, 0, result_bl); - if (!build_service_ticket_reply(principal_secret, info_vec, result_bl)) { - ret = -EIO; - break; - } - } - break; - - case 2: - { - struct CephXRequestHeader cephx_header; - ::decode(cephx_header, indata); - dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY " << cephx_header.request_type << dendl; - - bufferlist tmp_bl; - AuthServiceTicketInfo auth_ticket_info; - if (!verify_authorizer(mon->key_server, indata, auth_ticket_info, tmp_bl)) { - ret = -EPERM; - } - - AuthServiceTicketRequest ticket_req; - if (!verify_service_ticket_request(ticket_req, indata)) { - ret = -EPERM; - break; - } - dout(0) << " ticket_req.keys = " << ticket_req.keys << dendl; - - ret = 0; - vector info_vec; - for (uint32_t service_id = 1; service_id <= ticket_req.keys; service_id <<= 1) { - if (ticket_req.keys & service_id) { - dout(0) << " adding key for service " << service_id << dendl; - SessionAuthInfo info; - int r = mon->key_server.build_session_auth_info(service_id, auth_ticket_info, info); - if (r < 0) { - ret = r; - break; - } - info_vec.push_back(info); - } - } - build_cephx_response_header(cephx_header.request_type, ret, result_bl); - build_service_ticket_reply(auth_ticket_info.session_key, info_vec, result_bl); - } - break; - - default: - return -EINVAL; - } - - if (!ret || (ret == -EAGAIN)) { - state++; - } - dout(0) << "returning with state=" << state << dendl; - return ret; -} - -void CephAuthService_X::build_cephx_response_header(int request_type, int status, bufferlist& bl) -{ - struct CephXResponseHeader header; - header.request_type = request_type; - header.status = status; - ::encode(header, bl); -} - - -// -------------- +#include "cephx/CephxServiceHandler.h" -AuthServiceHandler *get_auth_handler(Monitor *mon, set<__u32>& supported) +AuthServiceHandler *get_auth_service_handler(KeyServer *ks, set<__u32>& supported) { if (supported.count(CEPH_AUTH_CEPHX)) - return new CephAuthService_X(mon); + return new CephxServiceHandler(ks); return NULL; } diff --git a/src/auth/AuthServiceHandler.h b/src/auth/AuthServiceHandler.h index 1430234acae1f..1cc0f3d117ad6 100644 --- a/src/auth/AuthServiceHandler.h +++ b/src/auth/AuthServiceHandler.h @@ -18,20 +18,15 @@ #include "include/types.h" #include "config.h" -class Monitor; +class KeyServer; -class AuthServiceHandler { -protected: - Monitor *mon; - -public: - AuthServiceHandler(Monitor *m) : mon(m) { } +struct AuthServiceHandler { virtual ~AuthServiceHandler() { } virtual int start_session(bufferlist& result) = 0; virtual int handle_request(bufferlist::iterator& indata, bufferlist& result) = 0; }; -extern AuthServiceHandler *get_auth_handler(Monitor *mon, set<__u32>& supported); +extern AuthServiceHandler *get_auth_service_handler(KeyServer *ks, set<__u32>& supported); #endif diff --git a/src/auth/cephx/CephxServiceHandler.cc b/src/auth/cephx/CephxServiceHandler.cc new file mode 100644 index 0000000000000..474b58421b9fa --- /dev/null +++ b/src/auth/cephx/CephxServiceHandler.cc @@ -0,0 +1,178 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2009 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#include "CephxServiceHandler.h" +#include "CephxProtocol.h" + +#include "../Auth.h" + +#include "mon/Monitor.h" + +#include +#include + +#include "config.h" + + +int CephxServiceHandler::start_session(bufferlist& result_bl) +{ + CephXEnvResponse1 response; + get_random_bytes((char *)&server_challenge, sizeof(server_challenge)); + response.server_challenge = server_challenge; + ::encode(response, result_bl); + state = 1; + return CEPH_AUTH_CEPHX; +} + +int CephxServiceHandler::handle_request(bufferlist::iterator& indata, bufferlist& result_bl) +{ + int ret = 0; + + dout(0) << "CephxServiceHandler: handle request" << dendl; + dout(0) << "state=" << state << dendl; + + switch (state) { + case 0: + assert(0); + break; + case 1: + { + CephXGetMonKey req; + ::decode(req, indata); + + entity_name = req.name; + + CryptoKey secret; + dout(0) << "entity_name=" << entity_name.to_str() << dendl; + if (!key_server->get_secret(entity_name, secret)) { + dout(0) << "couldn't find entity name: " << entity_name.to_str() << dendl; + ret = -EPERM; + break; + } + + bufferlist key, key_enc; + ::encode(server_challenge, key); + ::encode(req.client_challenge, key); + ret = encode_encrypt(key, secret, key_enc); + if (ret < 0) + break; + uint64_t expected_key = 0; + const uint64_t *p = (const uint64_t *)key_enc.c_str(); + for (int pos = 0; pos + sizeof(req.key) <= key_enc.length(); pos+=sizeof(req.key), p++) { + expected_key ^= *p; + } + dout(0) << "checking key: req.key=" << hex << req.key << " expected_key=" << expected_key << dec << dendl; + if (req.key != expected_key) { + dout(0) << "unexpected key: req.key=" << req.key << " expected_key=" << expected_key << dendl; + ret = -EPERM; + break; + } + + dout(0) << "CEPHX_GET_AUTH_SESSION_KEY" << dendl; + struct CephXRequestHeader cephx_header; + ::decode(cephx_header, indata); + + AuthAuthenticateRequest areq; + ::decode(areq, indata); + + CryptoKey session_key; + SessionAuthInfo info; + + CryptoKey principal_secret; + if (key_server->get_secret(areq.name, principal_secret) < 0) { + ret = -EPERM; + break; + } + + info.ticket.name = areq.name; + info.ticket.init_timestamps(g_clock.now(), g_conf.auth_mon_ticket_ttl); + + key_server->generate_secret(session_key); + + info.session_key = session_key; + info.service_id = CEPH_ENTITY_TYPE_AUTH; + if (!key_server->get_service_secret(CEPH_ENTITY_TYPE_AUTH, info.service_secret, info.secret_id)) { + dout(0) << "could not get service secret for auth subsystem" << dendl; + ret = -EIO; + break; + } + + vector info_vec; + info_vec.push_back(info); + + build_cephx_response_header(cephx_header.request_type, 0, result_bl); + if (!build_service_ticket_reply(principal_secret, info_vec, result_bl)) { + ret = -EIO; + break; + } + } + break; + + case 2: + { + struct CephXRequestHeader cephx_header; + ::decode(cephx_header, indata); + dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY " << cephx_header.request_type << dendl; + + bufferlist tmp_bl; + AuthServiceTicketInfo auth_ticket_info; + if (!verify_authorizer(*key_server, indata, auth_ticket_info, tmp_bl)) { + ret = -EPERM; + } + + AuthServiceTicketRequest ticket_req; + if (!verify_service_ticket_request(ticket_req, indata)) { + ret = -EPERM; + break; + } + dout(0) << " ticket_req.keys = " << ticket_req.keys << dendl; + + ret = 0; + vector info_vec; + for (uint32_t service_id = 1; service_id <= ticket_req.keys; service_id <<= 1) { + if (ticket_req.keys & service_id) { + dout(0) << " adding key for service " << service_id << dendl; + SessionAuthInfo info; + int r = key_server->build_session_auth_info(service_id, auth_ticket_info, info); + if (r < 0) { + ret = r; + break; + } + info_vec.push_back(info); + } + } + build_cephx_response_header(cephx_header.request_type, ret, result_bl); + build_service_ticket_reply(auth_ticket_info.session_key, info_vec, result_bl); + } + break; + + default: + return -EINVAL; + } + + if (!ret || (ret == -EAGAIN)) { + state++; + } + dout(0) << "returning with state=" << state << dendl; + return ret; +} + +void CephxServiceHandler::build_cephx_response_header(int request_type, int status, bufferlist& bl) +{ + struct CephXResponseHeader header; + header.request_type = request_type; + header.status = status; + ::encode(header, bl); +} diff --git a/src/auth/cephx/CephxServiceHandler.h b/src/auth/cephx/CephxServiceHandler.h new file mode 100644 index 0000000000000..839d02abfab00 --- /dev/null +++ b/src/auth/cephx/CephxServiceHandler.h @@ -0,0 +1,39 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2009 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __CEPHXSERVICEMANAGER_H +#define __CEPHXSERVICEMANAGER_H + +#include "../AuthServiceHandler.h" +#include "../Auth.h" + +class KeyServer; + +class CephxServiceHandler : public AuthServiceHandler { + KeyServer *key_server; + int state; + uint64_t server_challenge; + EntityName entity_name; + +public: + CephxServiceHandler(KeyServer *ks) : key_server(ks), state(0) {} + ~CephxServiceHandler() {} + + int start_session(bufferlist& result_bl); + int handle_request(bufferlist::iterator& indata, bufferlist& result_bl); + int handle_cephx_protocol(bufferlist::iterator& indata, bufferlist& result_bl); + void build_cephx_response_header(int request_type, int status, bufferlist& bl); +}; + +#endif diff --git a/src/mon/AuthMonitor.cc b/src/mon/AuthMonitor.cc index 7473976a01673..d6666005fdaab 100644 --- a/src/mon/AuthMonitor.cc +++ b/src/mon/AuthMonitor.cc @@ -280,7 +280,7 @@ bool AuthMonitor::preprocess_auth(MAuth *m) } if (!ret) { - s->auth_handler = get_auth_handler(mon, supported); + s->auth_handler = get_auth_service_handler(&mon->key_server, supported); if (!s->auth_handler) ret = -EPERM; else { -- 2.39.5