at v2.6.34-rc4 258 lines 5.6 kB view raw
1#include "ceph_debug.h" 2 3#include <linux/module.h> 4#include <linux/slab.h> 5#include <linux/err.h> 6 7#include "types.h" 8#include "auth_none.h" 9#include "auth_x.h" 10#include "decode.h" 11#include "super.h" 12 13#include "messenger.h" 14 15/* 16 * get protocol handler 17 */ 18static u32 supported_protocols[] = { 19 CEPH_AUTH_NONE, 20 CEPH_AUTH_CEPHX 21}; 22 23int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol) 24{ 25 switch (protocol) { 26 case CEPH_AUTH_NONE: 27 return ceph_auth_none_init(ac); 28 case CEPH_AUTH_CEPHX: 29 return ceph_x_init(ac); 30 default: 31 return -ENOENT; 32 } 33} 34 35/* 36 * setup, teardown. 37 */ 38struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) 39{ 40 struct ceph_auth_client *ac; 41 int ret; 42 43 dout("auth_init name '%s' secret '%s'\n", name, secret); 44 45 ret = -ENOMEM; 46 ac = kzalloc(sizeof(*ac), GFP_NOFS); 47 if (!ac) 48 goto out; 49 50 ac->negotiating = true; 51 if (name) 52 ac->name = name; 53 else 54 ac->name = CEPH_AUTH_NAME_DEFAULT; 55 dout("auth_init name %s secret %s\n", ac->name, secret); 56 ac->secret = secret; 57 return ac; 58 59out: 60 return ERR_PTR(ret); 61} 62 63void ceph_auth_destroy(struct ceph_auth_client *ac) 64{ 65 dout("auth_destroy %p\n", ac); 66 if (ac->ops) 67 ac->ops->destroy(ac); 68 kfree(ac); 69} 70 71/* 72 * Reset occurs when reconnecting to the monitor. 73 */ 74void ceph_auth_reset(struct ceph_auth_client *ac) 75{ 76 dout("auth_reset %p\n", ac); 77 if (ac->ops && !ac->negotiating) 78 ac->ops->reset(ac); 79 ac->negotiating = true; 80} 81 82int ceph_entity_name_encode(const char *name, void **p, void *end) 83{ 84 int len = strlen(name); 85 86 if (*p + 2*sizeof(u32) + len > end) 87 return -ERANGE; 88 ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT); 89 ceph_encode_32(p, len); 90 ceph_encode_copy(p, name, len); 91 return 0; 92} 93 94/* 95 * Initiate protocol negotiation with monitor. Include entity name 96 * and list supported protocols. 97 */ 98int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) 99{ 100 struct ceph_mon_request_header *monhdr = buf; 101 void *p = monhdr + 1, *end = buf + len, *lenp; 102 int i, num; 103 int ret; 104 105 dout("auth_build_hello\n"); 106 monhdr->have_version = 0; 107 monhdr->session_mon = cpu_to_le16(-1); 108 monhdr->session_mon_tid = 0; 109 110 ceph_encode_32(&p, 0); /* no protocol, yet */ 111 112 lenp = p; 113 p += sizeof(u32); 114 115 ceph_decode_need(&p, end, 1 + sizeof(u32), bad); 116 ceph_encode_8(&p, 1); 117 num = ARRAY_SIZE(supported_protocols); 118 ceph_encode_32(&p, num); 119 ceph_decode_need(&p, end, num * sizeof(u32), bad); 120 for (i = 0; i < num; i++) 121 ceph_encode_32(&p, supported_protocols[i]); 122 123 ret = ceph_entity_name_encode(ac->name, &p, end); 124 if (ret < 0) 125 return ret; 126 ceph_decode_need(&p, end, sizeof(u64), bad); 127 ceph_encode_64(&p, ac->global_id); 128 129 ceph_encode_32(&lenp, p - lenp - sizeof(u32)); 130 return p - buf; 131 132bad: 133 return -ERANGE; 134} 135 136int ceph_build_auth_request(struct ceph_auth_client *ac, 137 void *msg_buf, size_t msg_len) 138{ 139 struct ceph_mon_request_header *monhdr = msg_buf; 140 void *p = monhdr + 1; 141 void *end = msg_buf + msg_len; 142 int ret; 143 144 monhdr->have_version = 0; 145 monhdr->session_mon = cpu_to_le16(-1); 146 monhdr->session_mon_tid = 0; 147 148 ceph_encode_32(&p, ac->protocol); 149 150 ret = ac->ops->build_request(ac, p + sizeof(u32), end); 151 if (ret < 0) { 152 pr_err("error %d building request\n", ret); 153 return ret; 154 } 155 dout(" built request %d bytes\n", ret); 156 ceph_encode_32(&p, ret); 157 return p + ret - msg_buf; 158} 159 160/* 161 * Handle auth message from monitor. 162 */ 163int ceph_handle_auth_reply(struct ceph_auth_client *ac, 164 void *buf, size_t len, 165 void *reply_buf, size_t reply_len) 166{ 167 void *p = buf; 168 void *end = buf + len; 169 int protocol; 170 s32 result; 171 u64 global_id; 172 void *payload, *payload_end; 173 int payload_len; 174 char *result_msg; 175 int result_msg_len; 176 int ret = -EINVAL; 177 178 dout("handle_auth_reply %p %p\n", p, end); 179 ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad); 180 protocol = ceph_decode_32(&p); 181 result = ceph_decode_32(&p); 182 global_id = ceph_decode_64(&p); 183 payload_len = ceph_decode_32(&p); 184 payload = p; 185 p += payload_len; 186 ceph_decode_need(&p, end, sizeof(u32), bad); 187 result_msg_len = ceph_decode_32(&p); 188 result_msg = p; 189 p += result_msg_len; 190 if (p != end) 191 goto bad; 192 193 dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len, 194 result_msg, global_id, payload_len); 195 196 payload_end = payload + payload_len; 197 198 if (global_id && ac->global_id != global_id) { 199 dout(" set global_id %lld -> %lld\n", ac->global_id, global_id); 200 ac->global_id = global_id; 201 } 202 203 if (ac->negotiating) { 204 /* server does not support our protocols? */ 205 if (!protocol && result < 0) { 206 ret = result; 207 goto out; 208 } 209 /* set up (new) protocol handler? */ 210 if (ac->protocol && ac->protocol != protocol) { 211 ac->ops->destroy(ac); 212 ac->protocol = 0; 213 ac->ops = NULL; 214 } 215 if (ac->protocol != protocol) { 216 ret = ceph_auth_init_protocol(ac, protocol); 217 if (ret) { 218 pr_err("error %d on auth protocol %d init\n", 219 ret, protocol); 220 goto out; 221 } 222 } 223 224 ac->negotiating = false; 225 } 226 227 ret = ac->ops->handle_reply(ac, result, payload, payload_end); 228 if (ret == -EAGAIN) { 229 return ceph_build_auth_request(ac, reply_buf, reply_len); 230 } else if (ret) { 231 pr_err("authentication error %d\n", ret); 232 return ret; 233 } 234 return 0; 235 236bad: 237 pr_err("failed to decode auth msg\n"); 238out: 239 return ret; 240} 241 242int ceph_build_auth(struct ceph_auth_client *ac, 243 void *msg_buf, size_t msg_len) 244{ 245 if (!ac->protocol) 246 return ceph_auth_build_hello(ac, msg_buf, msg_len); 247 BUG_ON(!ac->ops); 248 if (!ac->ops->is_authenticated(ac)) 249 return ceph_build_auth_request(ac, msg_buf, msg_len); 250 return 0; 251} 252 253int ceph_auth_is_authenticated(struct ceph_auth_client *ac) 254{ 255 if (!ac->ops) 256 return 0; 257 return ac->ops->is_authenticated(ac); 258}