linux/net/rxrpc/server_key.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* RxRPC key management
   3 *
   4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 *
   7 * RxRPC keys should have a description of describing their purpose:
   8 *      "afs@CAMBRIDGE.REDHAT.COM>
   9 */
  10
  11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12
  13#include <crypto/skcipher.h>
  14#include <linux/module.h>
  15#include <linux/net.h>
  16#include <linux/skbuff.h>
  17#include <linux/key-type.h>
  18#include <linux/ctype.h>
  19#include <linux/slab.h>
  20#include <net/sock.h>
  21#include <net/af_rxrpc.h>
  22#include <keys/rxrpc-type.h>
  23#include <keys/user-type.h>
  24#include "ar-internal.h"
  25
  26static int rxrpc_vet_description_s(const char *);
  27static int rxrpc_preparse_s(struct key_preparsed_payload *);
  28static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
  29static void rxrpc_destroy_s(struct key *);
  30static void rxrpc_describe_s(const struct key *, struct seq_file *);
  31
  32/*
  33 * rxrpc server keys take "<serviceId>:<securityIndex>[:<sec-specific>]" as the
  34 * description and the key material as the payload.
  35 */
  36struct key_type key_type_rxrpc_s = {
  37        .name           = "rxrpc_s",
  38        .flags          = KEY_TYPE_NET_DOMAIN,
  39        .vet_description = rxrpc_vet_description_s,
  40        .preparse       = rxrpc_preparse_s,
  41        .free_preparse  = rxrpc_free_preparse_s,
  42        .instantiate    = generic_key_instantiate,
  43        .destroy        = rxrpc_destroy_s,
  44        .describe       = rxrpc_describe_s,
  45};
  46
  47/*
  48 * Vet the description for an RxRPC server key.
  49 */
  50static int rxrpc_vet_description_s(const char *desc)
  51{
  52        unsigned long service, sec_class;
  53        char *p;
  54
  55        service = simple_strtoul(desc, &p, 10);
  56        if (*p != ':' || service > 65535)
  57                return -EINVAL;
  58        sec_class = simple_strtoul(p + 1, &p, 10);
  59        if ((*p && *p != ':') || sec_class < 1 || sec_class > 255)
  60                return -EINVAL;
  61        return 0;
  62}
  63
  64/*
  65 * Preparse a server secret key.
  66 */
  67static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
  68{
  69        const struct rxrpc_security *sec;
  70        unsigned int service, sec_class;
  71        int n;
  72
  73        _enter("%zu", prep->datalen);
  74
  75        if (!prep->orig_description)
  76                return -EINVAL;
  77
  78        if (sscanf(prep->orig_description, "%u:%u%n", &service, &sec_class, &n) != 2)
  79                return -EINVAL;
  80
  81        sec = rxrpc_security_lookup(sec_class);
  82        if (!sec)
  83                return -ENOPKG;
  84
  85        prep->payload.data[1] = (struct rxrpc_security *)sec;
  86
  87        if (!sec->preparse_server_key)
  88                return -EINVAL;
  89
  90        return sec->preparse_server_key(prep);
  91}
  92
  93static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
  94{
  95        const struct rxrpc_security *sec = prep->payload.data[1];
  96
  97        if (sec && sec->free_preparse_server_key)
  98                sec->free_preparse_server_key(prep);
  99}
 100
 101static void rxrpc_destroy_s(struct key *key)
 102{
 103        const struct rxrpc_security *sec = key->payload.data[1];
 104
 105        if (sec && sec->destroy_server_key)
 106                sec->destroy_server_key(key);
 107}
 108
 109static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
 110{
 111        const struct rxrpc_security *sec = key->payload.data[1];
 112
 113        seq_puts(m, key->description);
 114        if (sec && sec->describe_server_key)
 115                sec->describe_server_key(key, m);
 116}
 117
 118/*
 119 * grab the security keyring for a server socket
 120 */
 121int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
 122{
 123        struct key *key;
 124        char *description;
 125
 126        _enter("");
 127
 128        if (optlen <= 0 || optlen > PAGE_SIZE - 1)
 129                return -EINVAL;
 130
 131        description = memdup_sockptr_nul(optval, optlen);
 132        if (IS_ERR(description))
 133                return PTR_ERR(description);
 134
 135        key = request_key(&key_type_keyring, description, NULL);
 136        if (IS_ERR(key)) {
 137                kfree(description);
 138                _leave(" = %ld", PTR_ERR(key));
 139                return PTR_ERR(key);
 140        }
 141
 142        rx->securities = key;
 143        kfree(description);
 144        _leave(" = 0 [key %x]", key->serial);
 145        return 0;
 146}
 147