1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/ceph/ceph_debug.h>
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/module.h>
5*4882a593Smuzhiyun #include <linux/err.h>
6*4882a593Smuzhiyun #include <linux/slab.h>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/ceph/types.h>
9*4882a593Smuzhiyun #include <linux/ceph/decode.h>
10*4882a593Smuzhiyun #include <linux/ceph/libceph.h>
11*4882a593Smuzhiyun #include <linux/ceph/messenger.h>
12*4882a593Smuzhiyun #include "auth_none.h"
13*4882a593Smuzhiyun #include "auth_x.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun /*
17*4882a593Smuzhiyun * get protocol handler
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun static u32 supported_protocols[] = {
20*4882a593Smuzhiyun CEPH_AUTH_NONE,
21*4882a593Smuzhiyun CEPH_AUTH_CEPHX
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun
ceph_auth_init_protocol(struct ceph_auth_client * ac,int protocol)24*4882a593Smuzhiyun static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun switch (protocol) {
27*4882a593Smuzhiyun case CEPH_AUTH_NONE:
28*4882a593Smuzhiyun return ceph_auth_none_init(ac);
29*4882a593Smuzhiyun case CEPH_AUTH_CEPHX:
30*4882a593Smuzhiyun return ceph_x_init(ac);
31*4882a593Smuzhiyun default:
32*4882a593Smuzhiyun return -ENOENT;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /*
37*4882a593Smuzhiyun * setup, teardown.
38*4882a593Smuzhiyun */
ceph_auth_init(const char * name,const struct ceph_crypto_key * key)39*4882a593Smuzhiyun struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun struct ceph_auth_client *ac;
42*4882a593Smuzhiyun int ret;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun dout("auth_init name '%s'\n", name);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun ret = -ENOMEM;
47*4882a593Smuzhiyun ac = kzalloc(sizeof(*ac), GFP_NOFS);
48*4882a593Smuzhiyun if (!ac)
49*4882a593Smuzhiyun goto out;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun mutex_init(&ac->mutex);
52*4882a593Smuzhiyun ac->negotiating = true;
53*4882a593Smuzhiyun if (name)
54*4882a593Smuzhiyun ac->name = name;
55*4882a593Smuzhiyun else
56*4882a593Smuzhiyun ac->name = CEPH_AUTH_NAME_DEFAULT;
57*4882a593Smuzhiyun dout("auth_init name %s\n", ac->name);
58*4882a593Smuzhiyun ac->key = key;
59*4882a593Smuzhiyun return ac;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun out:
62*4882a593Smuzhiyun return ERR_PTR(ret);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
ceph_auth_destroy(struct ceph_auth_client * ac)65*4882a593Smuzhiyun void ceph_auth_destroy(struct ceph_auth_client *ac)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun dout("auth_destroy %p\n", ac);
68*4882a593Smuzhiyun if (ac->ops)
69*4882a593Smuzhiyun ac->ops->destroy(ac);
70*4882a593Smuzhiyun kfree(ac);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun * Reset occurs when reconnecting to the monitor.
75*4882a593Smuzhiyun */
ceph_auth_reset(struct ceph_auth_client * ac)76*4882a593Smuzhiyun void ceph_auth_reset(struct ceph_auth_client *ac)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun mutex_lock(&ac->mutex);
79*4882a593Smuzhiyun dout("auth_reset %p\n", ac);
80*4882a593Smuzhiyun if (ac->ops && !ac->negotiating)
81*4882a593Smuzhiyun ac->ops->reset(ac);
82*4882a593Smuzhiyun ac->negotiating = true;
83*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /*
87*4882a593Smuzhiyun * EntityName, not to be confused with entity_name_t
88*4882a593Smuzhiyun */
ceph_auth_entity_name_encode(const char * name,void ** p,void * end)89*4882a593Smuzhiyun int ceph_auth_entity_name_encode(const char *name, void **p, void *end)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun int len = strlen(name);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (*p + 2*sizeof(u32) + len > end)
94*4882a593Smuzhiyun return -ERANGE;
95*4882a593Smuzhiyun ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
96*4882a593Smuzhiyun ceph_encode_32(p, len);
97*4882a593Smuzhiyun ceph_encode_copy(p, name, len);
98*4882a593Smuzhiyun return 0;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /*
102*4882a593Smuzhiyun * Initiate protocol negotiation with monitor. Include entity name
103*4882a593Smuzhiyun * and list supported protocols.
104*4882a593Smuzhiyun */
ceph_auth_build_hello(struct ceph_auth_client * ac,void * buf,size_t len)105*4882a593Smuzhiyun int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun struct ceph_mon_request_header *monhdr = buf;
108*4882a593Smuzhiyun void *p = monhdr + 1, *end = buf + len, *lenp;
109*4882a593Smuzhiyun int i, num;
110*4882a593Smuzhiyun int ret;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun mutex_lock(&ac->mutex);
113*4882a593Smuzhiyun dout("auth_build_hello\n");
114*4882a593Smuzhiyun monhdr->have_version = 0;
115*4882a593Smuzhiyun monhdr->session_mon = cpu_to_le16(-1);
116*4882a593Smuzhiyun monhdr->session_mon_tid = 0;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun ceph_encode_32(&p, CEPH_AUTH_UNKNOWN); /* no protocol, yet */
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun lenp = p;
121*4882a593Smuzhiyun p += sizeof(u32);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
124*4882a593Smuzhiyun ceph_encode_8(&p, 1);
125*4882a593Smuzhiyun num = ARRAY_SIZE(supported_protocols);
126*4882a593Smuzhiyun ceph_encode_32(&p, num);
127*4882a593Smuzhiyun ceph_decode_need(&p, end, num * sizeof(u32), bad);
128*4882a593Smuzhiyun for (i = 0; i < num; i++)
129*4882a593Smuzhiyun ceph_encode_32(&p, supported_protocols[i]);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun ret = ceph_auth_entity_name_encode(ac->name, &p, end);
132*4882a593Smuzhiyun if (ret < 0)
133*4882a593Smuzhiyun goto out;
134*4882a593Smuzhiyun ceph_decode_need(&p, end, sizeof(u64), bad);
135*4882a593Smuzhiyun ceph_encode_64(&p, ac->global_id);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun ceph_encode_32(&lenp, p - lenp - sizeof(u32));
138*4882a593Smuzhiyun ret = p - buf;
139*4882a593Smuzhiyun out:
140*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
141*4882a593Smuzhiyun return ret;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun bad:
144*4882a593Smuzhiyun ret = -ERANGE;
145*4882a593Smuzhiyun goto out;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
ceph_build_auth_request(struct ceph_auth_client * ac,void * msg_buf,size_t msg_len)148*4882a593Smuzhiyun static int ceph_build_auth_request(struct ceph_auth_client *ac,
149*4882a593Smuzhiyun void *msg_buf, size_t msg_len)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun struct ceph_mon_request_header *monhdr = msg_buf;
152*4882a593Smuzhiyun void *p = monhdr + 1;
153*4882a593Smuzhiyun void *end = msg_buf + msg_len;
154*4882a593Smuzhiyun int ret;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun monhdr->have_version = 0;
157*4882a593Smuzhiyun monhdr->session_mon = cpu_to_le16(-1);
158*4882a593Smuzhiyun monhdr->session_mon_tid = 0;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun ceph_encode_32(&p, ac->protocol);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun ret = ac->ops->build_request(ac, p + sizeof(u32), end);
163*4882a593Smuzhiyun if (ret < 0) {
164*4882a593Smuzhiyun pr_err("error %d building auth method %s request\n", ret,
165*4882a593Smuzhiyun ac->ops->name);
166*4882a593Smuzhiyun goto out;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun dout(" built request %d bytes\n", ret);
169*4882a593Smuzhiyun ceph_encode_32(&p, ret);
170*4882a593Smuzhiyun ret = p + ret - msg_buf;
171*4882a593Smuzhiyun out:
172*4882a593Smuzhiyun return ret;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /*
176*4882a593Smuzhiyun * Handle auth message from monitor.
177*4882a593Smuzhiyun */
ceph_handle_auth_reply(struct ceph_auth_client * ac,void * buf,size_t len,void * reply_buf,size_t reply_len)178*4882a593Smuzhiyun int ceph_handle_auth_reply(struct ceph_auth_client *ac,
179*4882a593Smuzhiyun void *buf, size_t len,
180*4882a593Smuzhiyun void *reply_buf, size_t reply_len)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun void *p = buf;
183*4882a593Smuzhiyun void *end = buf + len;
184*4882a593Smuzhiyun int protocol;
185*4882a593Smuzhiyun s32 result;
186*4882a593Smuzhiyun u64 global_id;
187*4882a593Smuzhiyun void *payload, *payload_end;
188*4882a593Smuzhiyun int payload_len;
189*4882a593Smuzhiyun char *result_msg;
190*4882a593Smuzhiyun int result_msg_len;
191*4882a593Smuzhiyun int ret = -EINVAL;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun mutex_lock(&ac->mutex);
194*4882a593Smuzhiyun dout("handle_auth_reply %p %p\n", p, end);
195*4882a593Smuzhiyun ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
196*4882a593Smuzhiyun protocol = ceph_decode_32(&p);
197*4882a593Smuzhiyun result = ceph_decode_32(&p);
198*4882a593Smuzhiyun global_id = ceph_decode_64(&p);
199*4882a593Smuzhiyun payload_len = ceph_decode_32(&p);
200*4882a593Smuzhiyun payload = p;
201*4882a593Smuzhiyun p += payload_len;
202*4882a593Smuzhiyun ceph_decode_need(&p, end, sizeof(u32), bad);
203*4882a593Smuzhiyun result_msg_len = ceph_decode_32(&p);
204*4882a593Smuzhiyun result_msg = p;
205*4882a593Smuzhiyun p += result_msg_len;
206*4882a593Smuzhiyun if (p != end)
207*4882a593Smuzhiyun goto bad;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
210*4882a593Smuzhiyun result_msg, global_id, payload_len);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun payload_end = payload + payload_len;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun if (global_id && ac->global_id != global_id) {
215*4882a593Smuzhiyun dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
216*4882a593Smuzhiyun ac->global_id = global_id;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (ac->negotiating) {
220*4882a593Smuzhiyun /* server does not support our protocols? */
221*4882a593Smuzhiyun if (!protocol && result < 0) {
222*4882a593Smuzhiyun ret = result;
223*4882a593Smuzhiyun goto out;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun /* set up (new) protocol handler? */
226*4882a593Smuzhiyun if (ac->protocol && ac->protocol != protocol) {
227*4882a593Smuzhiyun ac->ops->destroy(ac);
228*4882a593Smuzhiyun ac->protocol = 0;
229*4882a593Smuzhiyun ac->ops = NULL;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun if (ac->protocol != protocol) {
232*4882a593Smuzhiyun ret = ceph_auth_init_protocol(ac, protocol);
233*4882a593Smuzhiyun if (ret) {
234*4882a593Smuzhiyun pr_err("error %d on auth protocol %d init\n",
235*4882a593Smuzhiyun ret, protocol);
236*4882a593Smuzhiyun goto out;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun ac->negotiating = false;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun ret = ac->ops->handle_reply(ac, result, payload, payload_end);
244*4882a593Smuzhiyun if (ret == -EAGAIN) {
245*4882a593Smuzhiyun ret = ceph_build_auth_request(ac, reply_buf, reply_len);
246*4882a593Smuzhiyun } else if (ret) {
247*4882a593Smuzhiyun pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun out:
251*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
252*4882a593Smuzhiyun return ret;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun bad:
255*4882a593Smuzhiyun pr_err("failed to decode auth msg\n");
256*4882a593Smuzhiyun ret = -EINVAL;
257*4882a593Smuzhiyun goto out;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
ceph_build_auth(struct ceph_auth_client * ac,void * msg_buf,size_t msg_len)260*4882a593Smuzhiyun int ceph_build_auth(struct ceph_auth_client *ac,
261*4882a593Smuzhiyun void *msg_buf, size_t msg_len)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun int ret = 0;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun mutex_lock(&ac->mutex);
266*4882a593Smuzhiyun if (ac->ops->should_authenticate(ac))
267*4882a593Smuzhiyun ret = ceph_build_auth_request(ac, msg_buf, msg_len);
268*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
269*4882a593Smuzhiyun return ret;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
ceph_auth_is_authenticated(struct ceph_auth_client * ac)272*4882a593Smuzhiyun int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun int ret = 0;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun mutex_lock(&ac->mutex);
277*4882a593Smuzhiyun if (ac->ops)
278*4882a593Smuzhiyun ret = ac->ops->is_authenticated(ac);
279*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
280*4882a593Smuzhiyun return ret;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_is_authenticated);
283*4882a593Smuzhiyun
ceph_auth_create_authorizer(struct ceph_auth_client * ac,int peer_type,struct ceph_auth_handshake * auth)284*4882a593Smuzhiyun int ceph_auth_create_authorizer(struct ceph_auth_client *ac,
285*4882a593Smuzhiyun int peer_type,
286*4882a593Smuzhiyun struct ceph_auth_handshake *auth)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun int ret = 0;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun mutex_lock(&ac->mutex);
291*4882a593Smuzhiyun if (ac->ops && ac->ops->create_authorizer)
292*4882a593Smuzhiyun ret = ac->ops->create_authorizer(ac, peer_type, auth);
293*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
294*4882a593Smuzhiyun return ret;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_create_authorizer);
297*4882a593Smuzhiyun
ceph_auth_destroy_authorizer(struct ceph_authorizer * a)298*4882a593Smuzhiyun void ceph_auth_destroy_authorizer(struct ceph_authorizer *a)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun a->destroy(a);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_destroy_authorizer);
303*4882a593Smuzhiyun
ceph_auth_update_authorizer(struct ceph_auth_client * ac,int peer_type,struct ceph_auth_handshake * a)304*4882a593Smuzhiyun int ceph_auth_update_authorizer(struct ceph_auth_client *ac,
305*4882a593Smuzhiyun int peer_type,
306*4882a593Smuzhiyun struct ceph_auth_handshake *a)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun int ret = 0;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun mutex_lock(&ac->mutex);
311*4882a593Smuzhiyun if (ac->ops && ac->ops->update_authorizer)
312*4882a593Smuzhiyun ret = ac->ops->update_authorizer(ac, peer_type, a);
313*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
314*4882a593Smuzhiyun return ret;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_update_authorizer);
317*4882a593Smuzhiyun
ceph_auth_add_authorizer_challenge(struct ceph_auth_client * ac,struct ceph_authorizer * a,void * challenge_buf,int challenge_buf_len)318*4882a593Smuzhiyun int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac,
319*4882a593Smuzhiyun struct ceph_authorizer *a,
320*4882a593Smuzhiyun void *challenge_buf,
321*4882a593Smuzhiyun int challenge_buf_len)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun int ret = 0;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun mutex_lock(&ac->mutex);
326*4882a593Smuzhiyun if (ac->ops && ac->ops->add_authorizer_challenge)
327*4882a593Smuzhiyun ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf,
328*4882a593Smuzhiyun challenge_buf_len);
329*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
330*4882a593Smuzhiyun return ret;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge);
333*4882a593Smuzhiyun
ceph_auth_verify_authorizer_reply(struct ceph_auth_client * ac,struct ceph_authorizer * a)334*4882a593Smuzhiyun int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
335*4882a593Smuzhiyun struct ceph_authorizer *a)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun int ret = 0;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun mutex_lock(&ac->mutex);
340*4882a593Smuzhiyun if (ac->ops && ac->ops->verify_authorizer_reply)
341*4882a593Smuzhiyun ret = ac->ops->verify_authorizer_reply(ac, a);
342*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
343*4882a593Smuzhiyun return ret;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply);
346*4882a593Smuzhiyun
ceph_auth_invalidate_authorizer(struct ceph_auth_client * ac,int peer_type)347*4882a593Smuzhiyun void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun mutex_lock(&ac->mutex);
350*4882a593Smuzhiyun if (ac->ops && ac->ops->invalidate_authorizer)
351*4882a593Smuzhiyun ac->ops->invalidate_authorizer(ac, peer_type);
352*4882a593Smuzhiyun mutex_unlock(&ac->mutex);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
355