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