/*
* Authentication
*/
-
-static void encode_tgt(PrincipalTicket& ticket, CryptoKey& key, bufferlist& bl)
+#if 0
+static void encode_tgt(AuthTicket& ticket, CryptoKey& key, bufferlist& bl)
{
::encode(ticket, bl);
::encode(key, bl);
}
-static void decode_tgt(PrincipalTicket& ticket, CryptoKey& key, bufferlist& bl)
+static void decode_tgt(AuthTicket& ticket, CryptoKey& key, bufferlist& bl)
{
bufferlist::iterator iter = bl.begin();
::decode(ticket, iter);
::decode(key, iter);
}
-
+#endif
/*
* PRINCIPAL: request authentication
*
* principal_name, principal_addr. "please authenticate me."
*/
-void build_get_tgt_request(EntityName& principal_name, entity_addr_t principal_addr,
+void build_authenticate_request(EntityName& principal_name, entity_addr_t& principal_addr,
+ uint32_t keys,
+ bool encrypt,
+ CryptoKey& session_key,
+ AuthBlob& ticket_info,
bufferlist& request)
{
- ::encode(principal_name, request);
- ::encode(principal_addr, request);
+ AuthServiceTicketRequest ticket_req;
+
+ ticket_req.addr = principal_addr;
+ ticket_req.timestamp = g_clock.now();
+ ticket_req.keys = keys;
+ ::encode(ticket_req, request);
+ ::encode(ticket_info, request);
}
/*
* AUTH SERVER: authenticate
*
- * Authenticate principal, respond with TGT
+ * Authenticate principal, respond with AuthServiceTicketInfo
*
* {session key, validity, nonce}^principal_secret
* {principal_ticket, session key}^service_secret ... "enc_ticket"
*/
-bool build_get_tgt_reply(PrincipalTicket& principal_ticket,
+bool build_authenticate_reply(AuthTicket& ticket,
CryptoKey& session_key,
CryptoKey& principal_secret,
CryptoKey& service_secret,
bufferlist& reply)
{
- AuthMsg_A msg_a;
+ AuthServiceTicket msg_a;
msg_a.session_key = session_key;
if (msg_a.encode_encrypt(principal_secret, reply) < 0)
return false;
- TGT tgt;
+ AuthServiceTicketInfo tgt;
tgt.session_key = session_key;
- tgt.ticket = principal_ticket;
+ tgt.ticket = ticket;
if (tgt.encode_encrypt(service_secret, reply) < 0)
return false;
return true;
}
+bool verify_service_ticket_request(bool encrypted,
+ CryptoKey& service_secret,
+ CryptoKey& session_key,
+ uint32_t& keys,
+ bufferlist::iterator& indata)
+{
+ AuthServiceTicketRequest msg;
+
+ if (encrypted) {
+ if (msg.decode_decrypt(session_key, indata) < 0)
+ return false;
+
+ dout(0) << "decoded timestamp=" << msg.timestamp << " addr=" << msg.addr << dendl;
+
+ AuthServiceTicketInfo ticket_info;
+ if (ticket_info.decode_decrypt(service_secret, indata) < 0)
+ return false;
+ }
+
+ /* FIXME: validate that request makes sense */
+
+ return true;
+}
+
/*
* PRINCIPAL: verify our attempt to authenticate succeeded. fill out
* this ServiceTicket with the result.
*/
-bool ServiceTicket::verify_service_ticket_reply(CryptoKey& principal_secret,
+bool AuthTicketHandler::verify_service_ticket_reply(CryptoKey& secret,
bufferlist::iterator& indata)
{
dout(0) << "1" << dendl;
- AuthMsg_A msg_a;
- if (msg_a.decode_decrypt(principal_secret, indata) < 0)
+ AuthServiceTicket msg_a;
+ if (msg_a.decode_decrypt(secret, indata) < 0)
return false;
- ::decode(enc_ticket, indata);
+ ::decode(ticket, indata);
if (!indata.end())
return false;
return true;
}
+#if 0
/*
* PRINCIPAL: build request to retrieve a service ticket
*
- * TGT, D = {principal_addr, timestamp}^principal/auth session key
+ * AuthServiceTicketInfo, D = {principal_addr, timestamp}^principal/auth session key
*/
-bool ServiceTicket::get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl)
+bool AuthTicketHandler::get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl)
{
AuthMsg_D msg;
msg.timestamp = g_clock.now();
dout(0) << "decoded now=" << msg.timestamp << " addr=" << msg.principal_addr << dendl;
- TGT tgt;
+ AuthServiceTicketInfo tgt;
if (tgt.decode_decrypt(service_secret, indata) < 0)
return false;
return true;
}
-#if 0
-bool build_get_tgt_reply(PrincipalTicket& principal_ticket, CryptoKey& principal_secret,
+
+bool build_get_tgt_reply(AuthTicket& principal_ticket, CryptoKey& principal_secret,
CryptoKey& session_key, CryptoKey& service_secret,
bufferlist& reply)
{
::encode(enc_info, reply);
/*
- Build TGT
+ Build AuthServiceTicketInfo
*/
bufferlist ticket, tgt;
encode_tgt(principal_ticket, session_key, ticket);
return true;
}
#endif
+
+#if 0
/*
* AUTH SERVER: build ticket for service reply
*
* F= {principal/service session key, validity}^principal/auth session key
*
*/
-bool build_ticket_reply(ServiceTicket service_ticket,
+bool build_ticket_reply(AuthTicketHandler service_ticket,
CryptoKey session_key,
CryptoKey auth_session_key,
CryptoKey& service_secret,
return false;
- AuthMsg_F f;
+ AuthServiceTicket f;
f.session_key = session_key;
- f.validity = 0; /* FIXME */
if (f.encode_encrypt(auth_session_key, reply) < 0)
return false;
/*
* AUTH SERVER: verify a request to retrieve a service ticket, build response
*
- * TGT, {principal_addr, timestamp}^principal/auth session key
+ * AuthServiceTicketInfo, {principal_addr, timestamp}^principal/auth session key
*/
bool build_get_session_keys_response(ServiceTicket& ticket, CryptoKey& service_secret,
bufferlist::iterator& indata, bufferlist& out)
return true;
}
-
+#endif
/*
* PRINCIPAL: build authenticator to access the service.
*
* enc_ticket, {timestamp, nonce}^session_key
*/
-utime_t ServiceTicket::build_authenticator(bufferlist& bl)
+utime_t AuthTicketHandler::build_authenticator(bufferlist& bl)
{
utime_t now = g_clock.now();
- ::encode(enc_ticket, bl);
+ ::encode(ticket, bl);
bufferlist info, enc_info;
::encode(now, info);
::decode(enc_info, indata);
// decrypt ticket
- PrincipalTicket ticket;
+ AuthTicket ticket;
CryptoKey session_key;
{
bufferlist bl;
/*
* PRINCIPAL: verify reply is authentic
*/
-bool ServiceTicket::verify_reply_authenticator(utime_t then, bufferlist& enc_reply)
+bool AuthTicketHandler::verify_reply_authenticator(utime_t then, bufferlist& enc_reply)
{
bufferlist reply;
if (session_key.decrypt(enc_reply, reply) < 0)
/*
- * The principal ticket (if properly validated) authorizes the principal use
+ * The ticket (if properly validated) authorizes the principal use
* services as described by 'caps' during the specified validity
* period.
*/
-struct PrincipalTicket {
+struct AuthTicket {
entity_addr_t addr;
utime_t created, renew_after, expires;
string nonce;
::decode(flags, bl);
}
};
-WRITE_CLASS_ENCODER(PrincipalTicket)
+WRITE_CLASS_ENCODER(AuthTicket)
/*
* Authentication
*/
-extern void build_get_tgt_request(EntityName& principal_name, entity_addr_t principal_addr,
+extern void build_authenticate_request(EntityName& principal_name, entity_addr_t principal_addr,
bufferlist& request);
-extern bool build_get_tgt_reply(PrincipalTicket& principal_ticket, CryptoKey& principal_secret,
+extern bool build_authenticate_reply(AuthTicket& principal_ticket, CryptoKey& principal_secret,
CryptoKey& session_key, CryptoKey& service_secret,
bufferlist& reply);
+class AuthenticateRequest {
+ EntityName name;
+ entity_addr_t addr;
+public:
+ AuthenticateRequest(EntityName& principal_name, entity_addr_t principal_addr) : name(principal_name), addr(principal_addr) {}
+
+ void encode(bufferlist& bl) const {
+ ::encode(name, bl);
+ ::encode(addr, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(name, bl);
+ ::decode(addr, bl);
+ }
+};
+WRITE_CLASS_ENCODER(AuthenticateRequest)
+
+class AuthenticateReply {
+
+ bool verify() {
+ /* FIXME */
+ return false;
+ };
+};
+
struct AuthBlob {
bufferlist blob;
* ServiceTicket gives a principal access to some service
* (monitor, osd, mds).
*/
-struct ServiceTicket {
+struct AuthTicketHandler {
CryptoKey session_key;
- AuthBlob enc_ticket; // opaque to us
+ AuthBlob ticket; // opaque to us
string nonce;
utime_t renew_after, expires;
bool has_key_flag;
- ServiceTicket() : has_key_flag(false) {}
+ AuthTicketHandler() : has_key_flag(false) {}
+
+ bool build_authenticate_request();
+ bool verify_authenticate_response();
// to build our ServiceTicket
bool verify_service_ticket_reply(CryptoKey& principal_secret,
bool verify_reply_authenticator(utime_t then, bufferlist& enc_reply);
bool has_key() { return has_key_flag; }
+#if 0
void encode(bufferlist& bl) const {
__u8 v = 1;
::encode(v, bl);
::decode(f, bl);
has_key_flag = f;
}
+#endif
};
-WRITE_CLASS_ENCODER(ServiceTicket)
+//WRITE_CLASS_ENCODER(ServiceTicket)
struct AuthEnc {
virtual void encode(bufferlist& bl) const = 0;
}
};
+struct AuthServiceTicketRequest : public AuthEnc {
+ entity_addr_t addr;
+ utime_t timestamp;
+ uint32_t keys;
+
+ void encode(bufferlist& bl) const {
+ ::encode(addr, bl);
+ ::encode(timestamp, bl);
+ ::encode(keys, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(addr, bl);
+ ::decode(timestamp, bl);
+ ::decode(keys, bl);
+ }
+};
+WRITE_CLASS_ENCODER(AuthServiceTicketRequest);
+
/* A */
-struct AuthMsg_A : public AuthEnc {
- utime_t validity;
+struct AuthServiceTicket : public AuthEnc {
CryptoKey session_key;
+ utime_t validity;
void encode(bufferlist& bl) const {
::encode(session_key, bl);
::decode(validity, bl);
}
};
-WRITE_CLASS_ENCODER(AuthMsg_A);
+WRITE_CLASS_ENCODER(AuthServiceTicket);
+
/* B */
-struct TGT : public AuthEnc {
- PrincipalTicket ticket;
+struct AuthServiceTicketInfo : public AuthEnc {
+ AuthTicket ticket;
CryptoKey session_key;
void encode(bufferlist& bl) const {
::decode(session_key, bl);
}
};
-WRITE_CLASS_ENCODER(TGT);
+WRITE_CLASS_ENCODER(AuthServiceTicketInfo);
+#if 0
/* D */
struct AuthMsg_D : public AuthEnc {
entity_addr_t principal_addr;
WRITE_CLASS_ENCODER(AuthMsg_D);
-
/* E */
struct AuthMsg_E : public AuthEnc {
ServiceTicket ticket;
}
};
WRITE_CLASS_ENCODER(AuthMsg_E);
+#endif
-/* F */
-struct AuthMsg_F : public AuthEnc {
- CryptoKey session_key;
- utime_t validity;
-
- void encode(bufferlist& bl) const {
- ::encode(session_key, bl);
- ::encode(validity, bl);
- }
- void decode(bufferlist::iterator& bl) {
- ::decode(session_key, bl);
- ::decode(validity, bl);
- }
-};
-WRITE_CLASS_ENCODER(AuthMsg_F);
-extern bool verify_get_session_keys_request(CryptoKey& service_secret,
- CryptoKey& session_key, uint32_t& keys, bufferlist::iterator& indata);
+extern void build_authenticate_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_ticket_reply(ServiceTicket service_ticket,
+extern bool build_authenticate_reply(AuthTicketHandler ticket_handler,
CryptoKey session_key,
CryptoKey auth_session_key,
CryptoKey& service_secret,
/*
* Verify authenticator and generate reply authenticator
*/
+
+extern bool verify_service_ticket_request(bool encrypted,
+ CryptoKey& service_secret,
+ CryptoKey& session_key,
+ uint32_t& keys,
+ bufferlist::iterator& indata);
+
extern bool verify_authenticator(CryptoKey& service_secret, bufferlist::iterator& bl,
bufferlist& enc_reply);
char buf[1024];
const char *s = bl.c_str();
int pos = 0;
- for (int i=0; i<bl.length(); i++) {
- pos += snprintf(&buf[pos], 1024-pos, "%0.2x ", (int)(unsigned char)s[i]);
+ for (unsigned int i=0; i<bl.length(); i++) {
+ pos += snprintf(&buf[pos], 1024-pos, "%.2x ", (int)(unsigned char)s[i]);
if (i && !(i%8))
pos += snprintf(&buf[pos], 1024-pos, " ");
if (i && !(i%16))
{
CephXRequestHeader header;
- if (!auth_ticket.has_key()) {
+ if (!ticket_handler.has_key()) {
dout(0) << "auth ticket: doesn't have key" << dendl;
/* we first need to get the principle/auth session key */
header.request_type = CEPHX_GET_AUTH_SESSION_KEY;
::encode(header, bl);
- build_get_tgt_request(name, addr, bl);
+ CryptoKey key;
+ AuthBlob blob;
+ build_authenticate_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);
- auth_ticket.get_session_keys(want_keys, addr, bl);
+ build_authenticate_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);
- if (!auth_ticket.verify_service_ticket_reply(secret, indata)) {
+ if (!ticket_handler.verify_service_ticket_reply(secret, indata)) {
dout(0) << "could not verify authenticate reply" << dendl;
return -EPERM;
}
/* ceph-x protocol */
utime_t auth_ts;
- ServiceTicket auth_ticket;
+ AuthTicketHandler ticket_handler;
CryptoKey secret;
1. Obtaining principal/auth session key
+ (Authenticate Request)
p->a : principal, principal_addr. authenticate me!
...authenticator does lookup in database...
a->p : A= {principal/auth session key, validity}^principal_secret (*)
B= {principal ticket, validity, principal/auth session key}^authsecret
- B is also known as TGT
+
+ [principal/auth session key, validity] = service ticket
+ [principal ticket, validity, principal/auth session key] = service ticket info
(*) annotation: ^ signifies 'encrypted by'
a->p : E= {service ticket}^svcsecret
F= {principal/service session key, validity}^principal/auth session key
+ principal_addr, timestamp = authenticator
+
service ticket = principal name, client network address, validity, principal/service session key
Note that steps 1 and 2 are pretty much the same thing; contacting the
p->s : E + {principal_addr, timestamp}^principal/service session key
s->p : {timestamp+1}^principal/service/session key
+ timestamp+1 = reply authenticator
+
Now, the principal is fully authenticated with the service. So, logically we
have 2 main actions here. The first one would be to obtain a session key to
the service (steps 1 and 2), and the second one would be to authenticate with
the service, using that ticket.
*/
-#define CEPHX_PRINCIPAL_MON 0x0001
-#define CEPHX_PRINCIPAL_OSD 0x0002
-#define CEPHX_PRINCIPAL_MDS 0x0004
+#define CEPHX_PRINCIPAL_AUTH 0x0001
+#define CEPHX_PRINCIPAL_MON 0x0002
+#define CEPHX_PRINCIPAL_OSD 0x0004
+#define CEPHX_PRINCIPAL_MDS 0x0008
#define CEPHX_PRINCIPAL_TYPE_MASK 0x00FF
-#define CEPHX_GET_AUTH_SESSION_KEY 0x0100 /* Get TGT */
+#define CEPHX_GET_AUTH_SESSION_KEY 0x0100
#define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200
#define CEPHX_OPEN_SESSION 0x0300
class CephAuthServer {
/* FIXME: this is all temporary */
- PrincipalTicket principal_ticket;
+ AuthTicket ticket;
CryptoKey client_secret;
CryptoKey osd_secret;
CryptoKey auth_session_key;
dout(0) << "CEPHX_GET_AUTH_SESSION_KEY" << dendl;
EntityName name; /* FIXME should take it from the request */
entity_addr_t addr;
- PrincipalTicket ticket;
+ AuthTicket ticket;
CryptoKey principal_secret;
CryptoKey session_key;
CryptoKey service_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);
+
build_cephx_response_header(request_type, 0, result_bl);
- if (!build_get_tgt_reply(ticket, session_key, principal_secret, service_secret, result_bl)) {
+ if (!build_authenticate_reply(ticket, session_key, principal_secret, service_secret, result_bl)) {
ret = -EIO;
+ break;
}
-#if 0
- char buf[1024];
- const char *s = result_bl.c_str();
- int pos = 0;
- for (int i=0; i<result_bl.length(); i++) {
- pos += snprintf(&buf[pos], 1024-pos, "%0.2x ", (int)(unsigned char)s[i]);
- if (i && !(i%8))
- pos += snprintf(&buf[pos], 1024-pos, " ");
- if (i && !(i%16))
- pos += snprintf(&buf[pos], 1024-pos, "\n");
- }
- dout(0) << "result_buf=" << buf << dendl;
-#endif
}
break;
case CEPHX_GET_PRINCIPAL_SESSION_KEY:
auth_server.get_service_secret(service_secret);
auth_server.get_test_session_key(session_key);
- if (!verify_get_session_keys_request(service_secret,
+ if (!verify_service_ticket_request(true, service_secret,
auth_session_key, keys, indata)) {
ret = -EPERM;
+ break;
}
- ServiceTicket service_ticket;
+ AuthTicket service_ticket;
CryptoKey osd_secret;
auth_server.get_osd_secret(osd_secret);
auth_server.get_osd_secret(osd_secret);
build_cephx_response_header(request_type, ret, result_bl);
- build_ticket_reply(service_ticket, session_key, auth_session_key, osd_secret, result_bl);
+ build_authenticate_reply(service_ticket, session_key, auth_session_key, osd_secret, result_bl);
}
break;
default: