Blame view

net/ceph/auth.c 5.61 KB
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1
  #include <linux/ceph/ceph_debug.h>
4e7a5dcd1   Sage Weil   ceph: negotiate a...
2
3
4
  
  #include <linux/module.h>
  #include <linux/err.h>
d45d0d970   Sage Weil   ceph: add missing...
5
  #include <linux/slab.h>
4e7a5dcd1   Sage Weil   ceph: negotiate a...
6

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
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   Sage Weil   ceph: negotiate a...
11
  #include "auth_none.h"
ec0994e48   Sage Weil   ceph: add support...
12
  #include "auth_x.h"
4e7a5dcd1   Sage Weil   ceph: negotiate a...
13

4e7a5dcd1   Sage Weil   ceph: negotiate a...
14
15
16
17
18
  
  /*
   * get protocol handler
   */
  static u32 supported_protocols[] = {
ec0994e48   Sage Weil   ceph: add support...
19
20
  	CEPH_AUTH_NONE,
  	CEPH_AUTH_CEPHX
4e7a5dcd1   Sage Weil   ceph: negotiate a...
21
  };
cd84db6e4   Yehuda Sadeh   ceph: code cleanup
22
  static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
4e7a5dcd1   Sage Weil   ceph: negotiate a...
23
24
25
26
  {
  	switch (protocol) {
  	case CEPH_AUTH_NONE:
  		return ceph_auth_none_init(ac);
ec0994e48   Sage Weil   ceph: add support...
27
28
  	case CEPH_AUTH_CEPHX:
  		return ceph_x_init(ac);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
29
30
31
32
33
34
35
36
  	default:
  		return -ENOENT;
  	}
  }
  
  /*
   * setup, teardown.
   */
8323c3aa7   Tommi Virtanen   ceph: Move secret...
37
  struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key)
4e7a5dcd1   Sage Weil   ceph: negotiate a...
38
39
40
  {
  	struct ceph_auth_client *ac;
  	int ret;
8323c3aa7   Tommi Virtanen   ceph: Move secret...
41
42
  	dout("auth_init name '%s'
  ", name);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
43
44
45
46
47
48
49
50
51
52
53
  
  	ret = -ENOMEM;
  	ac = kzalloc(sizeof(*ac), GFP_NOFS);
  	if (!ac)
  		goto out;
  
  	ac->negotiating = true;
  	if (name)
  		ac->name = name;
  	else
  		ac->name = CEPH_AUTH_NAME_DEFAULT;
8323c3aa7   Tommi Virtanen   ceph: Move secret...
54
55
56
  	dout("auth_init name %s
  ", ac->name);
  	ac->key = key;
4e7a5dcd1   Sage Weil   ceph: negotiate a...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  	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)
  {
  	dout("auth_reset %p
  ", ac);
  	if (ac->ops && !ac->negotiating)
  		ac->ops->reset(ac);
  	ac->negotiating = true;
  }
  
  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;
  
  	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   Sage Weil   ceph: add struct ...
117
118
  	ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
  	ceph_encode_8(&p, 1);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
119
120
  	num = ARRAY_SIZE(supported_protocols);
  	ceph_encode_32(&p, num);
07c8739c5   Sage Weil   ceph: add struct ...
121
  	ceph_decode_need(&p, end, num * sizeof(u32), bad);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  	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)
  		return ret;
  	ceph_decode_need(&p, end, sizeof(u64), bad);
  	ceph_encode_64(&p, ac->global_id);
  
  	ceph_encode_32(&lenp, p - lenp - sizeof(u32));
  	return p - buf;
  
  bad:
  	return -ERANGE;
  }
cd84db6e4   Yehuda Sadeh   ceph: code cleanup
137
138
  static int ceph_build_auth_request(struct ceph_auth_client *ac,
  				   void *msg_buf, size_t msg_len)
9bd2e6f8b   Sage Weil   ceph: allow renew...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  {
  	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   Sage Weil   ceph: include aut...
153
154
155
  		pr_err("error %d building auth method %s request
  ", ret,
  		       ac->ops->name);
9bd2e6f8b   Sage Weil   ceph: allow renew...
156
157
158
159
160
161
162
  		return ret;
  	}
  	dout(" built request %d bytes
  ", ret);
  	ceph_encode_32(&p, ret);
  	return p + ret - msg_buf;
  }
4e7a5dcd1   Sage Weil   ceph: negotiate a...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  /*
   * 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;
  
  	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   Yehuda Sadeh   ceph: mount fails...
210
211
212
213
214
  		/* server does not support our protocols? */
  		if (!protocol && result < 0) {
  			ret = result;
  			goto out;
  		}
4e7a5dcd1   Sage Weil   ceph: negotiate a...
215
216
217
218
219
220
221
222
223
  		/* 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   Sage Weil   ceph: avoid possi...
224
225
226
  				pr_err("error %d on auth protocol %d init
  ",
  				       ret, protocol);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
227
228
229
  				goto out;
  			}
  		}
9bd2e6f8b   Sage Weil   ceph: allow renew...
230
231
  
  		ac->negotiating = false;
4e7a5dcd1   Sage Weil   ceph: negotiate a...
232
233
234
235
  	}
  
  	ret = ac->ops->handle_reply(ac, result, payload, payload_end);
  	if (ret == -EAGAIN) {
9bd2e6f8b   Sage Weil   ceph: allow renew...
236
  		return ceph_build_auth_request(ac, reply_buf, reply_len);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
237
  	} else if (ret) {
559c1e007   Sage Weil   ceph: include aut...
238
239
  		pr_err("auth method '%s' error %d
  ", ac->ops->name, ret);
4e7a5dcd1   Sage Weil   ceph: negotiate a...
240
241
242
243
244
245
246
247
248
249
  		return ret;
  	}
  	return 0;
  
  bad:
  	pr_err("failed to decode auth msg
  ");
  out:
  	return ret;
  }
9bd2e6f8b   Sage Weil   ceph: allow renew...
250
251
252
253
254
255
  int ceph_build_auth(struct ceph_auth_client *ac,
  		    void *msg_buf, size_t msg_len)
  {
  	if (!ac->protocol)
  		return ceph_auth_build_hello(ac, msg_buf, msg_len);
  	BUG_ON(!ac->ops);
a41359fa3   Sage Weil   ceph: renew auth ...
256
  	if (ac->ops->should_authenticate(ac))
9bd2e6f8b   Sage Weil   ceph: allow renew...
257
258
259
  		return ceph_build_auth_request(ac, msg_buf, msg_len);
  	return 0;
  }
4e7a5dcd1   Sage Weil   ceph: negotiate a...
260

9bd2e6f8b   Sage Weil   ceph: allow renew...
261
262
263
264
265
266
  int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
  {
  	if (!ac->ops)
  		return 0;
  	return ac->ops->is_authenticated(ac);
  }