Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* RxRPC security handling
0003  *
0004  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/net.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/udp.h>
0012 #include <linux/crypto.h>
0013 #include <net/sock.h>
0014 #include <net/af_rxrpc.h>
0015 #include <keys/rxrpc-type.h>
0016 #include "ar-internal.h"
0017 
0018 static const struct rxrpc_security *rxrpc_security_types[] = {
0019     [RXRPC_SECURITY_NONE]   = &rxrpc_no_security,
0020 #ifdef CONFIG_RXKAD
0021     [RXRPC_SECURITY_RXKAD]  = &rxkad,
0022 #endif
0023 };
0024 
0025 int __init rxrpc_init_security(void)
0026 {
0027     int i, ret;
0028 
0029     for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++) {
0030         if (rxrpc_security_types[i]) {
0031             ret = rxrpc_security_types[i]->init();
0032             if (ret < 0)
0033                 goto failed;
0034         }
0035     }
0036 
0037     return 0;
0038 
0039 failed:
0040     for (i--; i >= 0; i--)
0041         if (rxrpc_security_types[i])
0042             rxrpc_security_types[i]->exit();
0043     return ret;
0044 }
0045 
0046 void rxrpc_exit_security(void)
0047 {
0048     int i;
0049 
0050     for (i = 0; i < ARRAY_SIZE(rxrpc_security_types); i++)
0051         if (rxrpc_security_types[i])
0052             rxrpc_security_types[i]->exit();
0053 }
0054 
0055 /*
0056  * look up an rxrpc security module
0057  */
0058 const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
0059 {
0060     if (security_index >= ARRAY_SIZE(rxrpc_security_types))
0061         return NULL;
0062     return rxrpc_security_types[security_index];
0063 }
0064 
0065 /*
0066  * initialise the security on a client connection
0067  */
0068 int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
0069 {
0070     const struct rxrpc_security *sec;
0071     struct rxrpc_key_token *token;
0072     struct key *key = conn->params.key;
0073     int ret;
0074 
0075     _enter("{%d},{%x}", conn->debug_id, key_serial(key));
0076 
0077     if (!key)
0078         return 0;
0079 
0080     ret = key_validate(key);
0081     if (ret < 0)
0082         return ret;
0083 
0084     for (token = key->payload.data[0]; token; token = token->next) {
0085         sec = rxrpc_security_lookup(token->security_index);
0086         if (sec)
0087             goto found;
0088     }
0089     return -EKEYREJECTED;
0090 
0091 found:
0092     conn->security = sec;
0093 
0094     ret = conn->security->init_connection_security(conn, token);
0095     if (ret < 0) {
0096         conn->security = &rxrpc_no_security;
0097         return ret;
0098     }
0099 
0100     _leave(" = 0");
0101     return 0;
0102 }
0103 
0104 /*
0105  * Set the ops a server connection.
0106  */
0107 const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *rx,
0108                              struct sk_buff *skb)
0109 {
0110     const struct rxrpc_security *sec;
0111     struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
0112 
0113     _enter("");
0114 
0115     sec = rxrpc_security_lookup(sp->hdr.securityIndex);
0116     if (!sec) {
0117         trace_rxrpc_abort(0, "SVS",
0118                   sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
0119                   RX_INVALID_OPERATION, EKEYREJECTED);
0120         skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
0121         skb->priority = RX_INVALID_OPERATION;
0122         return NULL;
0123     }
0124 
0125     if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE &&
0126         !rx->securities) {
0127         trace_rxrpc_abort(0, "SVR",
0128                   sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
0129                   RX_INVALID_OPERATION, EKEYREJECTED);
0130         skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
0131         skb->priority = sec->no_key_abort;
0132         return NULL;
0133     }
0134 
0135     return sec;
0136 }
0137 
0138 /*
0139  * Find the security key for a server connection.
0140  */
0141 struct key *rxrpc_look_up_server_security(struct rxrpc_connection *conn,
0142                       struct sk_buff *skb,
0143                       u32 kvno, u32 enctype)
0144 {
0145     struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
0146     struct rxrpc_sock *rx;
0147     struct key *key = ERR_PTR(-EKEYREJECTED);
0148     key_ref_t kref = NULL;
0149     char kdesc[5 + 1 + 3 + 1 + 12 + 1 + 12 + 1];
0150     int ret;
0151 
0152     _enter("");
0153 
0154     if (enctype)
0155         sprintf(kdesc, "%u:%u:%u:%u",
0156             sp->hdr.serviceId, sp->hdr.securityIndex, kvno, enctype);
0157     else if (kvno)
0158         sprintf(kdesc, "%u:%u:%u",
0159             sp->hdr.serviceId, sp->hdr.securityIndex, kvno);
0160     else
0161         sprintf(kdesc, "%u:%u",
0162             sp->hdr.serviceId, sp->hdr.securityIndex);
0163 
0164     rcu_read_lock();
0165 
0166     rx = rcu_dereference(conn->params.local->service);
0167     if (!rx)
0168         goto out;
0169 
0170     /* look through the service's keyring */
0171     kref = keyring_search(make_key_ref(rx->securities, 1UL),
0172                   &key_type_rxrpc_s, kdesc, true);
0173     if (IS_ERR(kref)) {
0174         key = ERR_CAST(kref);
0175         goto out;
0176     }
0177 
0178     key = key_ref_to_ptr(kref);
0179 
0180     ret = key_validate(key);
0181     if (ret < 0) {
0182         key_put(key);
0183         key = ERR_PTR(ret);
0184         goto out;
0185     }
0186 
0187 out:
0188     rcu_read_unlock();
0189     return key;
0190 }