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 */
  58const 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        for (token = key->payload.data[0]; token; token = token->next) {
  85                sec = rxrpc_security_lookup(token->security_index);
  86                if (sec)
  87                        goto found;
  88        }
  89        return -EKEYREJECTED;
  90
  91found:
  92        conn->security = sec;
  93
  94        ret = conn->security->init_connection_security(conn, token);
  95        if (ret < 0) {
  96                conn->security = &rxrpc_no_security;
  97                return ret;
  98        }
  99
 100        _leave(" = 0");
 101        return 0;
 102}
 103
 104/*
 105 * Set the ops a server connection.
 106 */
 107const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *rx,
 108                                                         struct sk_buff *skb)
 109{
 110        const struct rxrpc_security *sec;
 111        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 112
 113        _enter("");
 114
 115        sec = rxrpc_security_lookup(sp->hdr.securityIndex);
 116        if (!sec) {
 117                trace_rxrpc_abort(0, "SVS",
 118                                  sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
 119                                  RX_INVALID_OPERATION, EKEYREJECTED);
 120                skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
 121                skb->priority = RX_INVALID_OPERATION;
 122                return NULL;
 123        }
 124
 125        if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE &&
 126            !rx->securities) {
 127                trace_rxrpc_abort(0, "SVR",
 128                                  sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
 129                                  RX_INVALID_OPERATION, EKEYREJECTED);
 130                skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
 131                skb->priority = sec->no_key_abort;
 132                return NULL;
 133        }
 134
 135        return sec;
 136}
 137
 138/*
 139 * Find the security key for a server connection.
 140 */
 141struct key *rxrpc_look_up_server_security(struct rxrpc_connection *conn,
 142                                          struct sk_buff *skb,
 143                                          u32 kvno, u32 enctype)
 144{
 145        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 146        struct rxrpc_sock *rx;
 147        struct key *key = ERR_PTR(-EKEYREJECTED);
 148        key_ref_t kref = NULL;
 149        char kdesc[5 + 1 + 3 + 1 + 12 + 1 + 12 + 1];
 150        int ret;
 151
 152        _enter("");
 153
 154        if (enctype)
 155                sprintf(kdesc, "%u:%u:%u:%u",
 156                        sp->hdr.serviceId, sp->hdr.securityIndex, kvno, enctype);
 157        else if (kvno)
 158                sprintf(kdesc, "%u:%u:%u",
 159                        sp->hdr.serviceId, sp->hdr.securityIndex, kvno);
 160        else
 161                sprintf(kdesc, "%u:%u",
 162                        sp->hdr.serviceId, sp->hdr.securityIndex);
 163
 164        rcu_read_lock();
 165
 166        rx = rcu_dereference(conn->params.local->service);
 167        if (!rx)
 168                goto out;
 169
 170        /* look through the service's keyring */
 171        kref = keyring_search(make_key_ref(rx->securities, 1UL),
 172                              &key_type_rxrpc_s, kdesc, true);
 173        if (IS_ERR(kref)) {
 174                key = ERR_CAST(kref);
 175                goto out;
 176        }
 177
 178        key = key_ref_to_ptr(kref);
 179
 180        ret = key_validate(key);
 181        if (ret < 0) {
 182                key_put(key);
 183                key = ERR_PTR(ret);
 184                goto out;
 185        }
 186
 187out:
 188        rcu_read_unlock();
 189        return key;
 190}
 191