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        return sec->preparse_server_key(prep);
  88}
  89
  90static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
  91{
  92        const struct rxrpc_security *sec = prep->payload.data[1];
  93
  94        if (sec)
  95                sec->free_preparse_server_key(prep);
  96}
  97
  98static void rxrpc_destroy_s(struct key *key)
  99{
 100        const struct rxrpc_security *sec = key->payload.data[1];
 101
 102        if (sec)
 103                sec->destroy_server_key(key);
 104}
 105
 106static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
 107{
 108        const struct rxrpc_security *sec = key->payload.data[1];
 109
 110        seq_puts(m, key->description);
 111        if (sec && sec->describe_server_key)
 112                sec->describe_server_key(key, m);
 113}
 114
 115/*
 116 * grab the security keyring for a server socket
 117 */
 118int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
 119{
 120        struct key *key;
 121        char *description;
 122
 123        _enter("");
 124
 125        if (optlen <= 0 || optlen > PAGE_SIZE - 1)
 126                return -EINVAL;
 127
 128        description = memdup_sockptr_nul(optval, optlen);
 129        if (IS_ERR(description))
 130                return PTR_ERR(description);
 131
 132        key = request_key(&key_type_keyring, description, NULL);
 133        if (IS_ERR(key)) {
 134                kfree(description);
 135                _leave(" = %ld", PTR_ERR(key));
 136                return PTR_ERR(key);
 137        }
 138
 139        rx->securities = key;
 140        kfree(description);
 141        _leave(" = 0 [key %x]", key->serial);
 142        return 0;
 143}
 144