1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
16 #include "CephxServiceHandler.h"
17 #include "CephxProtocol.h"
18 #include "CephxKeyServer.h"
22 #include "common/config.h"
23 #include "common/debug.h"
25 #define dout_subsys ceph_subsys_auth
27 #define dout_prefix *_dout << "cephx server " << entity_name << ": "
29 int CephxServiceHandler::start_session(EntityName
& name
, bufferlist::iterator
& indata
, bufferlist
& result_bl
, AuthCapsInfo
& caps
)
33 get_random_bytes((char *)&server_challenge
, sizeof(server_challenge
));
34 if (!server_challenge
)
35 server_challenge
= 1; // always non-zero.
36 ldout(cct
, 10) << "start_session server_challenge " << hex
<< server_challenge
<< dec
<< dendl
;
38 CephXServerChallenge ch
;
39 ch
.server_challenge
= server_challenge
;
40 ::encode(ch
, result_bl
);
41 return CEPH_AUTH_CEPHX
;
44 int CephxServiceHandler::handle_request(bufferlist::iterator
& indata
, bufferlist
& result_bl
, uint64_t& global_id
, AuthCapsInfo
& caps
, uint64_t *auid
)
48 struct CephXRequestHeader cephx_header
;
49 ::decode(cephx_header
, indata
);
52 switch (cephx_header
.request_type
) {
53 case CEPHX_GET_AUTH_SESSION_KEY
:
55 ldout(cct
, 10) << "handle_request get_auth_session_key for " << entity_name
<< dendl
;
57 CephXAuthenticate req
;
58 ::decode(req
, indata
);
61 if (!key_server
->get_secret(entity_name
, secret
)) {
62 ldout(cct
, 0) << "couldn't find entity name: " << entity_name
<< dendl
;
67 if (!server_challenge
) {
72 uint64_t expected_key
;
74 cephx_calc_client_server_challenge(cct
, secret
, server_challenge
,
75 req
.client_challenge
, &expected_key
, error
);
77 ldout(cct
, 0) << " cephx_calc_client_server_challenge error: " << error
<< dendl
;
82 ldout(cct
, 20) << " checking key: req.key=" << hex
<< req
.key
83 << " expected_key=" << expected_key
<< dec
<< dendl
;
84 if (req
.key
!= expected_key
) {
85 ldout(cct
, 0) << " unexpected key: req.key=" << hex
<< req
.key
86 << " expected_key=" << expected_key
<< dec
<< dendl
;
91 CryptoKey session_key
;
92 CephXSessionAuthInfo info
;
93 bool should_enc_ticket
= false;
96 if (! key_server
->get_auth(entity_name
, eauth
)) {
100 CephXServiceTicketInfo old_ticket_info
;
102 if (cephx_decode_ticket(cct
, key_server
, CEPH_ENTITY_TYPE_AUTH
,
103 req
.old_ticket
, old_ticket_info
)) {
104 global_id
= old_ticket_info
.ticket
.global_id
;
105 ldout(cct
, 10) << "decoded old_ticket with global_id=" << global_id
<< dendl
;
106 should_enc_ticket
= true;
109 info
.ticket
.init_timestamps(ceph_clock_now(), cct
->_conf
->auth_mon_ticket_ttl
);
110 info
.ticket
.name
= entity_name
;
111 info
.ticket
.global_id
= global_id
;
112 info
.ticket
.auid
= eauth
.auid
;
113 info
.validity
+= cct
->_conf
->auth_mon_ticket_ttl
;
115 if (auid
) *auid
= eauth
.auid
;
117 key_server
->generate_secret(session_key
);
119 info
.session_key
= session_key
;
120 info
.service_id
= CEPH_ENTITY_TYPE_AUTH
;
121 if (!key_server
->get_service_secret(CEPH_ENTITY_TYPE_AUTH
, info
.service_secret
, info
.secret_id
)) {
122 ldout(cct
, 0) << " could not get service secret for auth subsystem" << dendl
;
127 vector
<CephXSessionAuthInfo
> info_vec
;
128 info_vec
.push_back(info
);
130 build_cephx_response_header(cephx_header
.request_type
, 0, result_bl
);
131 if (!cephx_build_service_ticket_reply(cct
, eauth
.key
, info_vec
, should_enc_ticket
,
132 old_ticket_info
.session_key
, result_bl
)) {
136 if (!key_server
->get_service_caps(entity_name
, CEPH_ENTITY_TYPE_MON
, caps
)) {
137 ldout(cct
, 0) << " could not get mon caps for " << entity_name
<< dendl
;
140 char *caps_str
= caps
.caps
.c_str();
141 if (!caps_str
|| !caps_str
[0]) {
142 ldout(cct
,0) << "mon caps null for " << entity_name
<< dendl
;
149 case CEPHX_GET_PRINCIPAL_SESSION_KEY
:
151 ldout(cct
, 10) << "handle_request get_principal_session_key" << dendl
;
154 CephXServiceTicketInfo auth_ticket_info
;
155 // note: no challenge here.
156 if (!cephx_verify_authorizer(cct
, key_server
, indata
, auth_ticket_info
, nullptr,
162 CephXServiceTicketRequest ticket_req
;
163 ::decode(ticket_req
, indata
);
164 ldout(cct
, 10) << " ticket_req.keys = " << ticket_req
.keys
<< dendl
;
167 vector
<CephXSessionAuthInfo
> info_vec
;
168 int found_services
= 0;
170 for (uint32_t service_id
= 1; service_id
<= ticket_req
.keys
;
172 if (ticket_req
.keys
& service_id
) {
173 ldout(cct
, 10) << " adding key for service "
174 << ceph_entity_type_name(service_id
) << dendl
;
175 CephXSessionAuthInfo info
;
176 int r
= key_server
->build_session_auth_info(service_id
,
177 auth_ticket_info
, info
);
178 // tolerate missing MGR rotating key for the purposes of upgrades.
180 ldout(cct
, 10) << " missing key for service "
181 << ceph_entity_type_name(service_id
) << dendl
;
185 info
.validity
+= cct
->_conf
->auth_service_ticket_ttl
;
186 info_vec
.push_back(info
);
190 if (!found_services
&& service_err
) {
191 ldout(cct
, 10) << __func__
<< " did not find any service keys" << dendl
;
195 build_cephx_response_header(cephx_header
.request_type
, ret
, result_bl
);
196 cephx_build_service_ticket_reply(cct
, auth_ticket_info
.session_key
, info_vec
, false, no_key
, result_bl
);
200 case CEPHX_GET_ROTATING_KEY
:
202 ldout(cct
, 10) << "handle_request getting rotating secret for " << entity_name
<< dendl
;
203 build_cephx_response_header(cephx_header
.request_type
, 0, result_bl
);
204 if (!key_server
->get_rotating_encrypted(entity_name
, result_bl
)) {
212 ldout(cct
, 10) << "handle_request unknown op " << cephx_header
.request_type
<< dendl
;
218 void CephxServiceHandler::build_cephx_response_header(int request_type
, int status
, bufferlist
& bl
)
220 struct CephXResponseHeader header
;
221 header
.request_type
= request_type
;
222 header
.status
= status
;
223 ::encode(header
, bl
);