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