#include "config.h"
+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++) {
+ if (i && !(i%8))
+ pos += snprintf(&buf[pos], buf_len-pos, " ");
+ if (i && !(i%16))
+ pos += snprintf(&buf[pos], buf_len-pos, "\n");
+ pos += snprintf(&buf[pos], buf_len-pos, "%.2x ", (int)(unsigned char)s[i]);
+ }
+ dout(0) << msg << ":\n" << buf << dendl;
+}
+
+
+
/*
* Authentication
*
* principal_name, principal_addr. "please authenticate me."
*/
-void build_authenticate_request(EntityName& principal_name, entity_addr_t& principal_addr,
+void build_service_ticket_request(EntityName& principal_name, entity_addr_t& principal_addr,
uint32_t keys,
bool encrypt,
CryptoKey& session_key,
if (!encrypt) {
::encode(ticket_req, request);
} else {
+ bufferptr& s1 = session_key.get_secret();
+ hexdump("encoding, session key", s1.c_str(), s1.length());
encode_encrypt(ticket_req, session_key, request);
}
::encode(ticket_info, request);
* {session key, validity, nonce}^principal_secret
* {principal_ticket, session key}^service_secret ... "enc_ticket"
*/
-bool build_authenticate_reply(AuthTicket& ticket,
- CryptoKey& session_key,
+bool build_service_ticket_reply(
CryptoKey& principal_secret,
- CryptoKey& service_secret,
+ vector<SessionAuthInfo> ticket_info,
bufferlist& reply)
{
- AuthServiceTicket msg_a;
+ vector<SessionAuthInfo>::iterator ticket_iter = ticket_info.begin();
- msg_a.session_key = session_key;
- if (encode_encrypt(msg_a, principal_secret, reply) < 0)
- return false;
+ uint32_t num = ticket_info.size();
+ ::encode(num, reply);
- AuthServiceTicketInfo ticket_info;
- ticket_info.session_key = session_key;
- ticket_info.ticket = ticket;
- if (encode_encrypt(ticket_info, service_secret, reply) < 0)
- return false;
+ while (ticket_iter != ticket_info.end()) {
+ SessionAuthInfo& info = *ticket_iter;
+
+ ::encode(info.service_id, reply);
+
+ AuthServiceTicket msg_a;
+
+ msg_a.session_key = info.session_key;
+ if (encode_encrypt(msg_a, principal_secret, reply) < 0)
+ return false;
+
+ AuthServiceTicketInfo ticket_info;
+ ticket_info.session_key = info.session_key;
+ ticket_info.ticket = info.ticket;
+ if (encode_encrypt(ticket_info, info.service_secret, reply) < 0)
+ return false;
+
+ ++ticket_iter;
+ }
return true;
}
AuthServiceTicketRequest msg;
if (encrypted) {
+ bufferptr& s1 = session_key.get_secret();
+ hexdump("decoding, session key", s1.c_str(), s1.length());
+
dout(0) << "verify encrypted service ticket request" << dendl;
if (decode_decrypt(msg, session_key, indata) < 0)
return false;
bufferlist::iterator& indata)
{
AuthServiceTicket msg_a;
+
+ bufferptr& s1 = secret.get_secret();
+ hexdump("decoding, session key", s1.c_str(), s1.length());
if (decode_decrypt(msg_a, secret, indata) < 0)
return false;
-
+ /* FIXME: decode into relevant ticket */
::decode(ticket, indata);
+ bufferptr& s = msg_a.session_key.get_secret();
+ hexdump("decoded ticket.session key", s.c_str(), s.length());
+ session_key = msg_a.session_key;
+ has_key_flag = true;
+
+ return true;
+}
+
+/*
+ * PRINCIPAL: verify our attempt to authenticate succeeded. fill out
+ * this ServiceTicket with the result.
+ */
+bool AuthTicketsManager::verify_service_ticket_reply(CryptoKey& secret,
+ bufferlist::iterator& indata)
+{
+ uint32_t num;
+ ::decode(num, indata);
+ dout(0) << "received " << num << " keys" << dendl;
+
+ for (int i=0; i<(int)num; i++) {
+ uint32_t type;
+ ::decode(type, indata);
+ dout(0) << "received key type=" << type << dendl;
+ if (!tickets_map[type].verify_service_ticket_reply(secret, indata))
+ return false;
+ }
+
if (!indata.end())
return false;
- has_key_flag = true;
-
return true;
}
#include "Crypto.h"
#include "msg/msg_types.h"
+
struct EntityName {
uint32_t entity_type;
string name;
};
WRITE_CLASS_ENCODER(EntityName);
-
/*
* The ticket (if properly validated) authorizes the principal use
* services as described by 'caps' during the specified validity
};
WRITE_CLASS_ENCODER(AuthTicket)
+struct AuthBlob {
+ bufferlist blob;
+
+ void encode(bufferlist& bl) const {
+ ::encode(blob, bl);
+ }
+
+ void decode(bufferlist::iterator& bl) {
+ ::decode(blob, bl);
+ }
+};
+WRITE_CLASS_ENCODER(AuthBlob);
+
+struct SessionAuthInfo {
+ uint32_t service_id;
+ AuthTicket ticket;
+ CryptoKey session_key;
+ CryptoKey service_secret;
+};
+
+
/*
* Authentication
*/
-extern void build_authenticate_request(EntityName& principal_name, entity_addr_t principal_addr,
- bufferlist& request);
-extern bool build_authenticate_reply(AuthTicket& principal_ticket, CryptoKey& principal_secret,
- CryptoKey& session_key, CryptoKey& service_secret,
- bufferlist& reply);
+extern void build_service_ticket_request(EntityName& principal_name, entity_addr_t& principal_addr,
+ uint32_t keys,
+ bool encrypt,
+ CryptoKey& session_key,
+ AuthBlob& ticket_info,
+ bufferlist& request);
+
+extern bool build_service_ticket_reply(
+ CryptoKey& principal_secret,
+ vector<SessionAuthInfo> ticket_info,
+ bufferlist& reply);
class AuthenticateRequest {
EntityName name;
};
WRITE_CLASS_ENCODER(AuthenticateRequest)
-struct AuthBlob {
- bufferlist blob;
-
- void encode(bufferlist& bl) const {
- ::encode(blob, bl);
- }
-
- void decode(bufferlist::iterator& bl) {
- ::decode(blob, bl);
- }
-};
-WRITE_CLASS_ENCODER(AuthBlob);
-
/*
- * ServiceTicket gives a principal access to some service
- * (monitor, osd, mds).
+ * AuthTicketHandler
*/
struct AuthTicketHandler {
CryptoKey session_key;
// to build our ServiceTicket
bool verify_service_ticket_reply(CryptoKey& principal_secret,
bufferlist::iterator& indata);
-
+#if 0
// to build a new ServiceTicket, to access different service
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 has_key() { return has_key_flag; }
};
-//WRITE_CLASS_ENCODER(ServiceTicket)
+
+struct AuthTicketsManager {
+ map<uint32_t, AuthTicketHandler> tickets_map;
+
+ bool verify_service_ticket_reply(CryptoKey& principal_secret,
+ bufferlist::iterator& indata);
+
+ bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl);
+
+ AuthTicketHandler& get_handler(uint32_t type) { return tickets_map[type]; }
+};
struct AuthServiceTicketRequest {
entity_addr_t addr;
int AuthClientHandler::handle_response(int ret, bufferlist& bl)
{
-char buf[1024];
+char buf[4096];
const char *s = bl.c_str();
int pos = 0;
- for (unsigned int i=0; i<bl.length(); i++) {
- pos += snprintf(&buf[pos], 1024-pos, "%.2x ", (int)(unsigned char)s[i]);
+ for (unsigned int i=0; i<bl.length() && pos<sizeof(buf) - 8; i++) {
+ pos += snprintf(&buf[pos], sizeof(buf)-pos, "%.2x ", (int)(unsigned char)s[i]);
if (i && !(i%8))
- pos += snprintf(&buf[pos], 1024-pos, " ");
+ pos += snprintf(&buf[pos], sizeof(buf)-pos, " ");
if (i && !(i%16))
- pos += snprintf(&buf[pos], 1024-pos, "\n");
+ pos += snprintf(&buf[pos], sizeof(buf)-pos, "\n");
}
dout(0) << "result_buf=" << buf << dendl;
int AuthClientHandler::generate_cephx_protocol_request(bufferlist& bl)
{
CephXRequestHeader header;
-
+ AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
if (!ticket_handler.has_key()) {
dout(0) << "auth ticket: doesn't have key" << dendl;
/* we first need to get the principle/auth session key */
::encode(header, bl);
CryptoKey key;
AuthBlob blob;
- build_authenticate_request(name, addr, CEPHX_PRINCIPAL_AUTH,
+ build_service_ticket_request(name, addr, CEPHX_PRINCIPAL_AUTH,
false, key, blob, bl);
cephx_request_state = 1;
return 0;
header.request_type = CEPHX_GET_PRINCIPAL_SESSION_KEY;
::encode(header, bl);
- build_authenticate_request(name, addr, want_keys,
+ build_service_ticket_request(name, addr, want_keys,
true, ticket_handler.session_key, ticket_handler.ticket, bl);
return 0;
{
bufferptr p(PRINCIPAL_SECRET, sizeof(PRINCIPAL_SECRET) - 1);
secret.set_secret(CEPH_SECRET_AES, p);
+ // AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
- if (!ticket_handler.verify_service_ticket_reply(secret, indata)) {
- dout(0) << "could not verify authenticate reply" << dendl;
+ if (!tickets.verify_service_ticket_reply(secret, indata)) {
+ dout(0) << "could not verify service_ticket reply" << dendl;
return -EPERM;
}
cephx_response_state = 2;
dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY" << dendl;
{
+ AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
+
+ if (!tickets.verify_service_ticket_reply(ticket_handler.session_key, indata)) {
+ dout(0) << "could not verify service_ticket reply" << dendl;
+ return -EPERM;
+ }
}
ret = 0;
break;
/* ceph-x protocol */
utime_t auth_ts;
- AuthTicketHandler ticket_handler;
+ AuthTicketsManager tickets;
CryptoKey secret;
/* FIXME */
#define SERVICE_SECRET "0123456789ABCDEF"
#define AUTH_SESSION_KEY "23456789ABCDEF01"
-#define TEST_SESSION_KEY "456789ABCDEF0123"
+#define SESSION_KEY "456789ABCDEF0123"
#define PRINCIPAL_CLIENT_SECRET "123456789ABCDEF0"
#define PRINCIPAL_OSD_SECRET "3456789ABCDEF012"
+static inline 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++) {
+ if (i && !(i%8))
+ pos += snprintf(&buf[pos], buf_len-pos, " ");
+ if (i && !(i%16))
+ pos += snprintf(&buf[pos], buf_len-pos, "\n");
+ pos += snprintf(&buf[pos], buf_len-pos, "%.2x ", (int)(unsigned char)s[i]);
+ }
+ dout(0) << msg << ":\n" << buf << dendl;
+}
+
+
class CephAuthServer {
/* FIXME: this is all temporary */
AuthTicket ticket;
CryptoKey client_secret;
- CryptoKey osd_secret;
CryptoKey auth_session_key;
CryptoKey service_secret;
- CryptoKey test_session_key;
public:
CephAuthServer() {
bufferptr ptr2(PRINCIPAL_CLIENT_SECRET, sizeof(PRINCIPAL_CLIENT_SECRET) - 1);
client_secret.set_secret(CEPH_SECRET_AES, ptr2);
- bufferptr ptr3(PRINCIPAL_OSD_SECRET, sizeof(PRINCIPAL_OSD_SECRET) - 1);
- osd_secret.set_secret(CEPH_SECRET_AES, ptr2);
-
bufferptr ptr4(AUTH_SESSION_KEY, sizeof(AUTH_SESSION_KEY) - 1);
- auth_session_key.set_secret(CEPH_SECRET_AES, ptr3);
-
- bufferptr ptr5(TEST_SESSION_KEY, sizeof(TEST_SESSION_KEY) - 1);
- test_session_key.set_secret(CEPH_SECRET_AES, ptr5);
+ auth_session_key.set_secret(CEPH_SECRET_AES, ptr4);
}
/* FIXME: temporary stabs */
return 0;
}
- int get_osd_secret(CryptoKey& secret) {
- secret = osd_secret;
- return 0;
- }
+ int get_service_secret(CryptoKey& secret, uint32_t service_id) {
+ char buf[16];
+ memcpy(buf, SERVICE_SECRET, 16);
+ buf[0] = service_id & 0xFF;
+ bufferptr ptr(buf, 16);
+ secret.set_secret(CEPH_SECRET_AES, ptr);
- int get_service_secret(CryptoKey& secret) {
- secret = service_secret;
return 0;
}
- int get_auth_session_key(CryptoKey& key) {
- key = auth_session_key;
- return 0;
- }
+ int get_service_session_key(CryptoKey& secret, uint32_t service_id) {
+ char buf[16];
+ memcpy(buf, SERVICE_SECRET, 16);
+ buf[0] = service_id & 0xFF;
+ bufferptr ptr(buf, 16);
+ secret.set_secret(CEPH_SECRET_AES, ptr);
- int get_test_session_key(CryptoKey& key) {
- key = test_session_key;
return 0;
}
};
AuthTicket ticket;
CryptoKey principal_secret;
CryptoKey session_key;
- CryptoKey service_secret;
+ CryptoKey auth_secret;
ticket.expires = g_clock.now();
uint32_t keys;
- if (!verify_service_ticket_request(false, service_secret,
- session_key, keys, indata)) {
- ret = -EPERM;
- break;
- }
-
auth_server.get_client_secret(principal_secret);
- auth_server.get_auth_session_key(session_key);
- auth_server.get_service_secret(service_secret);
+ auth_server.get_service_session_key(session_key, CEPHX_PRINCIPAL_AUTH);
+ auth_server.get_service_secret(auth_secret, CEPHX_PRINCIPAL_AUTH);
+ if (!verify_service_ticket_request(false, auth_secret,
+ session_key, keys, indata)) {
+ ret = -EPERM;
+ break;
+ }
build_cephx_response_header(request_type, 0, result_bl);
- if (!build_authenticate_reply(ticket, session_key, principal_secret, service_secret, result_bl)) {
+ vector<SessionAuthInfo> info_vec;
+ SessionAuthInfo info;
+ info.ticket = ticket;
+ info.service_id = CEPHX_PRINCIPAL_AUTH;
+ info.session_key = session_key;
+ info.service_secret = auth_secret;
+ info_vec.push_back(info);
+ if (!build_service_ticket_reply(principal_secret, info_vec, result_bl)) {
ret = -EIO;
break;
}
{
EntityName name; /* FIXME should take it from the request */
entity_addr_t addr;
+ CryptoKey auth_secret;
CryptoKey auth_session_key;
CryptoKey session_key;
CryptoKey service_secret;
uint32_t keys;
- auth_server.get_auth_session_key(session_key);
- auth_server.get_service_secret(service_secret);
- auth_server.get_test_session_key(session_key);
+ auth_server.get_service_secret(auth_secret, CEPHX_PRINCIPAL_AUTH);
+ auth_server.get_service_session_key(auth_session_key, CEPHX_PRINCIPAL_AUTH);
+
+ vector<SessionAuthInfo> info_vec;
- if (!verify_service_ticket_request(true, service_secret,
+ if (!verify_service_ticket_request(true, auth_secret,
auth_session_key, keys, indata)) {
ret = -EPERM;
break;
}
- AuthTicket service_ticket;
- CryptoKey osd_secret;
- auth_server.get_osd_secret(osd_secret);
+ auth_server.get_service_session_key(auth_session_key, CEPHX_PRINCIPAL_AUTH);
+
+ for (uint32_t service_id = 1; service_id != (CEPHX_PRINCIPAL_TYPE_MASK + 1); service_id <<= 1) {
+ if (keys & service_id) {
+ auth_server.get_service_secret(service_secret, service_id);
+
+ SessionAuthInfo info;
+
+ AuthTicket service_ticket;
+ /* FIXME: initialize service_ticket */
+
+ auth_server.get_service_secret(service_secret, service_id);
+ auth_server.get_service_session_key(session_key, service_id);
+
+ info.service_id = service_id;
+ info.ticket = service_ticket;
+ info.session_key = session_key;
+ info.service_secret = service_secret;
+
+ info_vec.push_back(info);
+ }
+ }
- auth_server.get_osd_secret(osd_secret);
build_cephx_response_header(request_type, ret, result_bl);
+ build_service_ticket_reply(auth_session_key, info_vec, result_bl);
- build_authenticate_reply(service_ticket, session_key, auth_session_key, osd_secret, result_bl);
ret = 0;
}
break;