security.c (4093B)
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}