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