linux/net/rxrpc/security.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* RxRPC security handling
   3 *
   4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/net.h>
  10#include <linux/skbuff.h>
  11#include <linux/udp.h>
  12#include <linux/crypto.h>
  13#include <net/sock.h>
  14#include <net/af_rxrpc.h>
  15#include <keys/rxrpc-type.h>
  16#include "ar-internal.h"
  17
  18static const struct rxrpc_security *rxrpc_security_types[] = {
  19        [RXRPC_SECURITY_NONE]   = &rxrpc_no_security,
  20#ifdef CONFIG_RXKAD
  21        [RXRPC_SECURITY_RXKAD]  = &rxkad,
  22#endif
  23};
  24
  25int __init rxrpc_init_security(void)
  26{
  27        int i, ret;
  28
  29        for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) {
  30                if (rxrpc_security_types[i]) {
  31                        ret = rxrpc_security_types[i]->init();
  32                        if (ret < 0)
  33                                goto failed;
  34                }
  35        }
  36
  37        return 0;
  38
  39failed:
  40        for (i--; i >= 0; i--)
  41                if (rxrpc_security_types[i])
  42                        rxrpc_security_types[i]->exit();
  43        return ret;
  44}
  45
  46void rxrpc_exit_security(void)
  47{
  48        int i;
  49
  50        for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++)
  51                if (rxrpc_security_types[i])
  52                        rxrpc_security_types[i]->exit();
  53}
  54
  55/*
  56 * look up an rxrpc security module
  57 */
  58static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
  59{
  60        if (security_index >= ARRAY_SIZE(rxrpc_security_types))
  61                return NULL;
  62        return rxrpc_security_types[security_index];
  63}
  64
  65/*
  66 * initialise the security on a client connection
  67 */
  68int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
  69{
  70        const struct rxrpc_security *sec;
  71        struct rxrpc_key_token *token;
  72        struct key *key = conn->params.key;
  73        int ret;
  74
  75        _enter("{%d},{%x}", conn->debug_id, key_serial(key));
  76
  77        if (!key)
  78                return 0;
  79
  80        ret = key_validate(key);
  81        if (ret < 0)
  82                return ret;
  83
  84        token = key->payload.data[0];
  85        if (!token)
  86                return -EKEYREJECTED;
  87
  88        sec = rxrpc_security_lookup(token->security_index);
  89        if (!sec)
  90                return -EKEYREJECTED;
  91        conn->security = sec;
  92
  93        ret = conn->security->init_connection_security(conn);
  94        if (ret < 0) {
  95                conn->security = &rxrpc_no_security;
  96                return ret;
  97        }
  98
  99        _leave(" = 0");
 100        return 0;
 101}
 102
 103/*
 104 * initialise the security on a server connection
 105 */
 106int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
 107{
 108        const struct rxrpc_security *sec;
 109        struct rxrpc_local *local = conn->params.local;
 110        struct rxrpc_sock *rx;
 111        struct key *key;
 112        key_ref_t kref;
 113        char kdesc[5 + 1 + 3 + 1];
 114
 115        _enter("");
 116
 117        sprintf(kdesc, "%u:%u", conn->service_id, conn->security_ix);
 118
 119        sec = rxrpc_security_lookup(conn->security_ix);
 120        if (!sec) {
 121                _leave(" = -ENOKEY [lookup]");
 122                return -ENOKEY;
 123        }
 124
 125        /* find the service */
 126        read_lock(&local->services_lock);
 127        rx = rcu_dereference_protected(local->service,
 128                                       lockdep_is_held(&local->services_lock));
 129        if (rx && (rx->srx.srx_service == conn->service_id ||
 130                   rx->second_service == conn->service_id))
 131                goto found_service;
 132
 133        /* the service appears to have died */
 134        read_unlock(&local->services_lock);
 135        _leave(" = -ENOENT");
 136        return -ENOENT;
 137
 138found_service:
 139        if (!rx->securities) {
 140                read_unlock(&local->services_lock);
 141                _leave(" = -ENOKEY");
 142                return -ENOKEY;
 143        }
 144
 145        /* look through the service's keyring */
 146        kref = keyring_search(make_key_ref(rx->securities, 1UL),
 147                              &key_type_rxrpc_s, kdesc, true);
 148        if (IS_ERR(kref)) {
 149                read_unlock(&local->services_lock);
 150                _leave(" = %ld [search]", PTR_ERR(kref));
 151                return PTR_ERR(kref);
 152        }
 153
 154        key = key_ref_to_ptr(kref);
 155        read_unlock(&local->services_lock);
 156
 157        conn->server_key = key;
 158        conn->security = sec;
 159
 160        _leave(" = 0");
 161        return 0;
 162}
 163