| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* RxRPC security handling |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * Written by David Howells (dhowells@redhat.com) |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or |
|---|
| 7 | | - * modify it under the terms of the GNU General Public License |
|---|
| 8 | | - * as published by the Free Software Foundation; either version |
|---|
| 9 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 105 | 101 | } |
|---|
| 106 | 102 | |
|---|
| 107 | 103 | /* |
|---|
| 108 | | - * initialise the security on a server connection |
|---|
| 104 | + * Find the security key for a server connection. |
|---|
| 109 | 105 | */ |
|---|
| 110 | | -int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) |
|---|
| 106 | +bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock *rx, |
|---|
| 107 | + const struct rxrpc_security **_sec, |
|---|
| 108 | + struct key **_key, |
|---|
| 109 | + struct sk_buff *skb) |
|---|
| 111 | 110 | { |
|---|
| 112 | 111 | const struct rxrpc_security *sec; |
|---|
| 113 | | - struct rxrpc_local *local = conn->params.local; |
|---|
| 114 | | - struct rxrpc_sock *rx; |
|---|
| 115 | | - struct key *key; |
|---|
| 116 | | - key_ref_t kref; |
|---|
| 112 | + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
|---|
| 113 | + key_ref_t kref = NULL; |
|---|
| 117 | 114 | char kdesc[5 + 1 + 3 + 1]; |
|---|
| 118 | 115 | |
|---|
| 119 | 116 | _enter(""); |
|---|
| 120 | 117 | |
|---|
| 121 | | - sprintf(kdesc, "%u:%u", conn->service_id, conn->security_ix); |
|---|
| 118 | + sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex); |
|---|
| 122 | 119 | |
|---|
| 123 | | - sec = rxrpc_security_lookup(conn->security_ix); |
|---|
| 120 | + sec = rxrpc_security_lookup(sp->hdr.securityIndex); |
|---|
| 124 | 121 | if (!sec) { |
|---|
| 125 | | - _leave(" = -ENOKEY [lookup]"); |
|---|
| 126 | | - return -ENOKEY; |
|---|
| 122 | + trace_rxrpc_abort(0, "SVS", |
|---|
| 123 | + sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, |
|---|
| 124 | + RX_INVALID_OPERATION, EKEYREJECTED); |
|---|
| 125 | + skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; |
|---|
| 126 | + skb->priority = RX_INVALID_OPERATION; |
|---|
| 127 | + return false; |
|---|
| 127 | 128 | } |
|---|
| 128 | 129 | |
|---|
| 129 | | - /* find the service */ |
|---|
| 130 | | - read_lock(&local->services_lock); |
|---|
| 131 | | - rx = rcu_dereference_protected(local->service, |
|---|
| 132 | | - lockdep_is_held(&local->services_lock)); |
|---|
| 133 | | - if (rx && (rx->srx.srx_service == conn->service_id || |
|---|
| 134 | | - rx->second_service == conn->service_id)) |
|---|
| 135 | | - goto found_service; |
|---|
| 130 | + if (sp->hdr.securityIndex == RXRPC_SECURITY_NONE) |
|---|
| 131 | + goto out; |
|---|
| 136 | 132 | |
|---|
| 137 | | - /* the service appears to have died */ |
|---|
| 138 | | - read_unlock(&local->services_lock); |
|---|
| 139 | | - _leave(" = -ENOENT"); |
|---|
| 140 | | - return -ENOENT; |
|---|
| 141 | | - |
|---|
| 142 | | -found_service: |
|---|
| 143 | 133 | if (!rx->securities) { |
|---|
| 144 | | - read_unlock(&local->services_lock); |
|---|
| 145 | | - _leave(" = -ENOKEY"); |
|---|
| 146 | | - return -ENOKEY; |
|---|
| 134 | + trace_rxrpc_abort(0, "SVR", |
|---|
| 135 | + sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, |
|---|
| 136 | + RX_INVALID_OPERATION, EKEYREJECTED); |
|---|
| 137 | + skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; |
|---|
| 138 | + skb->priority = RX_INVALID_OPERATION; |
|---|
| 139 | + return false; |
|---|
| 147 | 140 | } |
|---|
| 148 | 141 | |
|---|
| 149 | 142 | /* look through the service's keyring */ |
|---|
| 150 | 143 | kref = keyring_search(make_key_ref(rx->securities, 1UL), |
|---|
| 151 | | - &key_type_rxrpc_s, kdesc); |
|---|
| 144 | + &key_type_rxrpc_s, kdesc, true); |
|---|
| 152 | 145 | if (IS_ERR(kref)) { |
|---|
| 153 | | - read_unlock(&local->services_lock); |
|---|
| 154 | | - _leave(" = %ld [search]", PTR_ERR(kref)); |
|---|
| 155 | | - return PTR_ERR(kref); |
|---|
| 146 | + trace_rxrpc_abort(0, "SVK", |
|---|
| 147 | + sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, |
|---|
| 148 | + sec->no_key_abort, EKEYREJECTED); |
|---|
| 149 | + skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; |
|---|
| 150 | + skb->priority = sec->no_key_abort; |
|---|
| 151 | + return false; |
|---|
| 156 | 152 | } |
|---|
| 157 | 153 | |
|---|
| 158 | | - key = key_ref_to_ptr(kref); |
|---|
| 159 | | - read_unlock(&local->services_lock); |
|---|
| 160 | | - |
|---|
| 161 | | - conn->server_key = key; |
|---|
| 162 | | - conn->security = sec; |
|---|
| 163 | | - |
|---|
| 164 | | - _leave(" = 0"); |
|---|
| 165 | | - return 0; |
|---|
| 154 | +out: |
|---|
| 155 | + *_sec = sec; |
|---|
| 156 | + *_key = key_ref_to_ptr(kref); |
|---|
| 157 | + return true; |
|---|
| 166 | 158 | } |
|---|