auth.c 5.4 KB

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