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
  85/*
  86 * EntityName, not to be confused with entity_name_t
  87 */
  88int ceph_auth_entity_name_encode(const char *name, void **p, void *end)
  89{
  90        int len = strlen(name);
  91
  92        if (*p + 2*sizeof(u32) + len > end)
  93                return -ERANGE;
  94        ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
  95        ceph_encode_32(p, len);
  96        ceph_encode_copy(p, name, len);
  97        return 0;
  98}
  99
 100/*
 101 * Initiate protocol negotiation with monitor.  Include entity name
 102 * and list supported protocols.
 103 */
 104int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
 105{
 106        struct ceph_mon_request_header *monhdr = buf;
 107        void *p = monhdr + 1, *end = buf + len, *lenp;
 108        int i, num;
 109        int ret;
 110
 111        mutex_lock(&ac->mutex);
 112        dout("auth_build_hello\n");
 113        monhdr->have_version = 0;
 114        monhdr->session_mon = cpu_to_le16(-1);
 115        monhdr->session_mon_tid = 0;
 116
 117        ceph_encode_32(&p, CEPH_AUTH_UNKNOWN);  /* no protocol, yet */
 118
 119        lenp = p;
 120        p += sizeof(u32);
 121
 122        ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
 123        ceph_encode_8(&p, 1);
 124        num = ARRAY_SIZE(supported_protocols);
 125        ceph_encode_32(&p, num);
 126        ceph_decode_need(&p, end, num * sizeof(u32), bad);
 127        for (i = 0; i < num; i++)
 128                ceph_encode_32(&p, supported_protocols[i]);
 129
 130        ret = ceph_auth_entity_name_encode(ac->name, &p, end);
 131        if (ret < 0)
 132                goto out;
 133        ceph_decode_need(&p, end, sizeof(u64), bad);
 134        ceph_encode_64(&p, ac->global_id);
 135
 136        ceph_encode_32(&lenp, p - lenp - sizeof(u32));
 137        ret = p - buf;
 138out:
 139        mutex_unlock(&ac->mutex);
 140        return ret;
 141
 142bad:
 143        ret = -ERANGE;
 144        goto out;
 145}
 146
 147static int ceph_build_auth_request(struct ceph_auth_client *ac,
 148                                   void *msg_buf, size_t msg_len)
 149{
 150        struct ceph_mon_request_header *monhdr = msg_buf;
 151        void *p = monhdr + 1;
 152        void *end = msg_buf + msg_len;
 153        int ret;
 154
 155        monhdr->have_version = 0;
 156        monhdr->session_mon = cpu_to_le16(-1);
 157        monhdr->session_mon_tid = 0;
 158
 159        ceph_encode_32(&p, ac->protocol);
 160
 161        ret = ac->ops->build_request(ac, p + sizeof(u32), end);
 162        if (ret < 0) {
 163                pr_err("error %d building auth method %s request\n", ret,
 164                       ac->ops->name);
 165                goto out;
 166        }
 167        dout(" built request %d bytes\n", ret);
 168        ceph_encode_32(&p, ret);
 169        ret = p + ret - msg_buf;
 170out:
 171        return ret;
 172}
 173
 174/*
 175 * Handle auth message from monitor.
 176 */
 177int ceph_handle_auth_reply(struct ceph_auth_client *ac,
 178                           void *buf, size_t len,
 179                           void *reply_buf, size_t reply_len)
 180{
 181        void *p = buf;
 182        void *end = buf + len;
 183        int protocol;
 184        s32 result;
 185        u64 global_id;
 186        void *payload, *payload_end;
 187        int payload_len;
 188        char *result_msg;
 189        int result_msg_len;
 190        int ret = -EINVAL;
 191
 192        mutex_lock(&ac->mutex);
 193        dout("handle_auth_reply %p %p\n", p, end);
 194        ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
 195        protocol = ceph_decode_32(&p);
 196        result = ceph_decode_32(&p);
 197        global_id = ceph_decode_64(&p);
 198        payload_len = ceph_decode_32(&p);
 199        payload = p;
 200        p += payload_len;
 201        ceph_decode_need(&p, end, sizeof(u32), bad);
 202        result_msg_len = ceph_decode_32(&p);
 203        result_msg = p;
 204        p += result_msg_len;
 205        if (p != end)
 206                goto bad;
 207
 208        dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
 209             result_msg, global_id, payload_len);
 210
 211        payload_end = payload + payload_len;
 212
 213        if (global_id && ac->global_id != global_id) {
 214                dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
 215                ac->global_id = global_id;
 216        }
 217
 218        if (ac->negotiating) {
 219                /* server does not support our protocols? */
 220                if (!protocol && result < 0) {
 221                        ret = result;
 222                        goto out;
 223                }
 224                /* set up (new) protocol handler? */
 225                if (ac->protocol && ac->protocol != protocol) {
 226                        ac->ops->destroy(ac);
 227                        ac->protocol = 0;
 228                        ac->ops = NULL;
 229                }
 230                if (ac->protocol != protocol) {
 231                        ret = ceph_auth_init_protocol(ac, protocol);
 232                        if (ret) {
 233                                pr_err("error %d on auth protocol %d init\n",
 234                                       ret, protocol);
 235                                goto out;
 236                        }
 237                }
 238
 239                ac->negotiating = false;
 240        }
 241
 242        ret = ac->ops->handle_reply(ac, result, payload, payload_end);
 243        if (ret == -EAGAIN) {
 244                ret = ceph_build_auth_request(ac, reply_buf, reply_len);
 245        } else if (ret) {
 246                pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
 247        }
 248
 249out:
 250        mutex_unlock(&ac->mutex);
 251        return ret;
 252
 253bad:
 254        pr_err("failed to decode auth msg\n");
 255        ret = -EINVAL;
 256        goto out;
 257}
 258
 259int ceph_build_auth(struct ceph_auth_client *ac,
 260                    void *msg_buf, size_t msg_len)
 261{
 262        int ret = 0;
 263
 264        mutex_lock(&ac->mutex);
 265        if (ac->ops->should_authenticate(ac))
 266                ret = ceph_build_auth_request(ac, msg_buf, msg_len);
 267        mutex_unlock(&ac->mutex);
 268        return ret;
 269}
 270
 271int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
 272{
 273        int ret = 0;
 274
 275        mutex_lock(&ac->mutex);
 276        if (ac->ops)
 277                ret = ac->ops->is_authenticated(ac);
 278        mutex_unlock(&ac->mutex);
 279        return ret;
 280}
 281EXPORT_SYMBOL(ceph_auth_is_authenticated);
 282
 283int ceph_auth_create_authorizer(struct ceph_auth_client *ac,
 284                                int peer_type,
 285                                struct ceph_auth_handshake *auth)
 286{
 287        int ret = 0;
 288
 289        mutex_lock(&ac->mutex);
 290        if (ac->ops && ac->ops->create_authorizer)
 291                ret = ac->ops->create_authorizer(ac, peer_type, auth);
 292        mutex_unlock(&ac->mutex);
 293        return ret;
 294}
 295EXPORT_SYMBOL(ceph_auth_create_authorizer);
 296
 297void ceph_auth_destroy_authorizer(struct ceph_authorizer *a)
 298{
 299        a->destroy(a);
 300}
 301EXPORT_SYMBOL(ceph_auth_destroy_authorizer);
 302
 303int ceph_auth_update_authorizer(struct ceph_auth_client *ac,
 304                                int peer_type,
 305                                struct ceph_auth_handshake *a)
 306{
 307        int ret = 0;
 308
 309        mutex_lock(&ac->mutex);
 310        if (ac->ops && ac->ops->update_authorizer)
 311                ret = ac->ops->update_authorizer(ac, peer_type, a);
 312        mutex_unlock(&ac->mutex);
 313        return ret;
 314}
 315EXPORT_SYMBOL(ceph_auth_update_authorizer);
 316
 317int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
 318                                      struct ceph_authorizer *a)
 319{
 320        int ret = 0;
 321
 322        mutex_lock(&ac->mutex);
 323        if (ac->ops && ac->ops->verify_authorizer_reply)
 324                ret = ac->ops->verify_authorizer_reply(ac, a);
 325        mutex_unlock(&ac->mutex);
 326        return ret;
 327}
 328EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply);
 329
 330void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type)
 331{
 332        mutex_lock(&ac->mutex);
 333        if (ac->ops && ac->ops->invalidate_authorizer)
 334                ac->ops->invalidate_authorizer(ac, peer_type);
 335        mutex_unlock(&ac->mutex);
 336}
 337EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
 338