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 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
 136static int 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 auth method %s request\n", ret,
 153                       ac->ops->name);
 154                return ret;
 155        }
 156        dout(" built request %d bytes\n", ret);
 157        ceph_encode_32(&p, ret);
 158        return p + ret - msg_buf;
 159}
 160
 161/*
 162 * Handle auth message from monitor.
 163 */
 164int ceph_handle_auth_reply(struct ceph_auth_client *ac,
 165                           void *buf, size_t len,
 166                           void *reply_buf, size_t reply_len)
 167{
 168        void *p = buf;
 169        void *end = buf + len;
 170        int protocol;
 171        s32 result;
 172        u64 global_id;
 173        void *payload, *payload_end;
 174        int payload_len;
 175        char *result_msg;
 176        int result_msg_len;
 177        int ret = -EINVAL;
 178
 179        dout("handle_auth_reply %p %p\n", p, end);
 180        ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
 181        protocol = ceph_decode_32(&p);
 182        result = ceph_decode_32(&p);
 183        global_id = ceph_decode_64(&p);
 184        payload_len = ceph_decode_32(&p);
 185        payload = p;
 186        p += payload_len;
 187        ceph_decode_need(&p, end, sizeof(u32), bad);
 188        result_msg_len = ceph_decode_32(&p);
 189        result_msg = p;
 190        p += result_msg_len;
 191        if (p != end)
 192                goto bad;
 193
 194        dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
 195             result_msg, global_id, payload_len);
 196
 197        payload_end = payload + payload_len;
 198
 199        if (global_id && ac->global_id != global_id) {
 200                dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
 201                ac->global_id = global_id;
 202        }
 203
 204        if (ac->negotiating) {
 205                /* server does not support our protocols? */
 206                if (!protocol && result < 0) {
 207                        ret = result;
 208                        goto out;
 209                }
 210                /* set up (new) protocol handler? */
 211                if (ac->protocol && ac->protocol != protocol) {
 212                        ac->ops->destroy(ac);
 213                        ac->protocol = 0;
 214                        ac->ops = NULL;
 215                }
 216                if (ac->protocol != protocol) {
 217                        ret = ceph_auth_init_protocol(ac, protocol);
 218                        if (ret) {
 219                                pr_err("error %d on auth protocol %d init\n",
 220                                       ret, protocol);
 221                                goto out;
 222                        }
 223                }
 224
 225                ac->negotiating = false;
 226        }
 227
 228        ret = ac->ops->handle_reply(ac, result, payload, payload_end);
 229        if (ret == -EAGAIN) {
 230                return ceph_build_auth_request(ac, reply_buf, reply_len);
 231        } else if (ret) {
 232                pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
 233                return ret;
 234        }
 235        return 0;
 236
 237bad:
 238        pr_err("failed to decode auth msg\n");
 239out:
 240        return ret;
 241}
 242
 243int ceph_build_auth(struct ceph_auth_client *ac,
 244                    void *msg_buf, size_t msg_len)
 245{
 246        if (!ac->protocol)
 247                return ceph_auth_build_hello(ac, msg_buf, msg_len);
 248        BUG_ON(!ac->ops);
 249        if (ac->ops->should_authenticate(ac))
 250                return ceph_build_auth_request(ac, msg_buf, msg_len);
 251        return 0;
 252}
 253
 254int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
 255{
 256        if (!ac->ops)
 257                return 0;
 258        return ac->ops->is_authenticated(ac);
 259}
 260