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