2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-04-26 15:48:28 -07:00
/* RxRPC security handling
*
* Copyright ( C ) 2007 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*/
# include <linux/module.h>
# include <linux/net.h>
# include <linux/skbuff.h>
# include <linux/udp.h>
# include <linux/crypto.h>
# include <net/sock.h>
# include <net/af_rxrpc.h>
2009-09-14 01:17:35 +00:00
# include <keys/rxrpc-type.h>
2007-04-26 15:48:28 -07:00
# include "ar-internal.h"
2016-04-07 17:23:51 +01:00
static const struct rxrpc_security * rxrpc_security_types [ ] = {
2016-04-07 17:23:58 +01:00
[ RXRPC_SECURITY_NONE ] = & rxrpc_no_security ,
2016-04-07 17:23:51 +01:00
# ifdef CONFIG_RXKAD
[ RXRPC_SECURITY_RXKAD ] = & rxkad ,
# endif
} ;
2007-04-26 15:48:28 -07:00
2016-04-07 17:23:51 +01:00
int __init rxrpc_init_security ( void )
2007-04-26 15:48:28 -07:00
{
2016-04-07 17:23:51 +01:00
int i , ret ;
2007-04-26 15:48:28 -07:00
2016-04-07 17:23:51 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( rxrpc_security_types ) ; i + + ) {
if ( rxrpc_security_types [ i ] ) {
ret = rxrpc_security_types [ i ] - > init ( ) ;
if ( ret < 0 )
goto failed ;
2007-04-26 15:48:28 -07:00
}
}
2016-04-07 17:23:51 +01:00
return 0 ;
failed :
for ( i - - ; i > = 0 ; i - - )
if ( rxrpc_security_types [ i ] )
rxrpc_security_types [ i ] - > exit ( ) ;
return ret ;
2007-04-26 15:48:28 -07:00
}
2016-04-07 17:23:51 +01:00
void rxrpc_exit_security ( void )
2007-04-26 15:48:28 -07:00
{
2016-04-07 17:23:51 +01:00
int i ;
2007-04-26 15:48:28 -07:00
2016-04-07 17:23:51 +01:00
for ( i = 0 ; i < ARRAY_SIZE ( rxrpc_security_types ) ; i + + )
if ( rxrpc_security_types [ i ] )
rxrpc_security_types [ i ] - > exit ( ) ;
2007-04-26 15:48:28 -07:00
}
2016-04-07 17:23:51 +01:00
/*
* look up an rxrpc security module
2007-04-26 15:48:28 -07:00
*/
2020-09-16 08:37:29 +01:00
const struct rxrpc_security * rxrpc_security_lookup ( u8 security_index )
2007-04-26 15:48:28 -07:00
{
2016-04-07 17:23:51 +01:00
if ( security_index > = ARRAY_SIZE ( rxrpc_security_types ) )
return NULL ;
return rxrpc_security_types [ security_index ] ;
2007-04-26 15:48:28 -07:00
}
2022-10-20 21:58:36 +01:00
/*
* Initialise the security on a client call .
*/
int rxrpc_init_client_call_security ( struct rxrpc_call * call )
{
2022-12-15 16:19:56 +00:00
const struct rxrpc_security * sec = & rxrpc_no_security ;
2022-10-20 21:58:36 +01:00
struct rxrpc_key_token * token ;
struct key * key = call - > key ;
int ret ;
if ( ! key )
2022-12-15 16:19:56 +00:00
goto found ;
2022-10-20 21:58:36 +01:00
ret = key_validate ( key ) ;
if ( ret < 0 )
return ret ;
for ( token = key - > payload . data [ 0 ] ; token ; token = token - > next ) {
sec = rxrpc_security_lookup ( token - > security_index ) ;
if ( sec )
goto found ;
}
return - EKEYREJECTED ;
found :
call - > security = sec ;
2022-12-15 16:19:56 +00:00
call - > security_ix = sec - > security_index ;
2022-10-20 21:58:36 +01:00
return 0 ;
}
2007-04-26 15:48:28 -07:00
/*
* initialise the security on a client connection
*/
int rxrpc_init_client_conn_security ( struct rxrpc_connection * conn )
{
2009-09-14 01:17:35 +00:00
struct rxrpc_key_token * token ;
2022-10-19 13:49:02 +01:00
struct key * key = conn - > key ;
2022-10-19 09:45:43 +01:00
int ret = 0 ;
2007-04-26 15:48:28 -07:00
_enter ( " {%d},{%x} " , conn - > debug_id , key_serial ( key ) ) ;
2020-09-16 08:19:12 +01:00
for ( token = key - > payload . data [ 0 ] ; token ; token = token - > next ) {
2022-10-19 09:45:43 +01:00
if ( token - > security_index = = conn - > security - > security_index )
2020-09-16 08:19:12 +01:00
goto found ;
}
return - EKEYREJECTED ;
2009-09-14 01:17:35 +00:00
2020-09-16 08:19:12 +01:00
found :
2022-10-19 09:45:43 +01:00
mutex_lock ( & conn - > security_lock ) ;
if ( conn - > state = = RXRPC_CONN_CLIENT_UNSECURED ) {
ret = conn - > security - > init_connection_security ( conn , token ) ;
if ( ret = = 0 ) {
spin_lock ( & conn - > state_lock ) ;
if ( conn - > state = = RXRPC_CONN_CLIENT_UNSECURED )
conn - > state = RXRPC_CONN_CLIENT ;
spin_unlock ( & conn - > state_lock ) ;
}
2007-04-26 15:48:28 -07:00
}
2022-10-19 09:45:43 +01:00
mutex_unlock ( & conn - > security_lock ) ;
return ret ;
2007-04-26 15:48:28 -07:00
}
/*
2020-09-16 08:00:44 +01:00
* Set the ops a server connection .
2007-04-26 15:48:28 -07:00
*/
2020-09-16 08:00:44 +01:00
const struct rxrpc_security * rxrpc_get_incoming_security ( struct rxrpc_sock * rx ,
struct sk_buff * skb )
2007-04-26 15:48:28 -07:00
{
2016-04-07 17:23:51 +01:00
const struct rxrpc_security * sec ;
2019-12-20 16:17:16 +00:00
struct rxrpc_skb_priv * sp = rxrpc_skb ( skb ) ;
2007-04-26 15:48:28 -07:00
_enter ( " " ) ;
2019-12-20 16:17:16 +00:00
sec = rxrpc_security_lookup ( sp - > hdr . securityIndex ) ;
2007-04-26 15:48:28 -07:00
if ( ! sec ) {
2022-10-06 21:45:42 +01:00
rxrpc_direct_abort ( skb , rxrpc_abort_unsupported_security ,
RX_INVALID_OPERATION , - EKEYREJECTED ) ;
2020-09-16 08:00:44 +01:00
return NULL ;
2007-04-26 15:48:28 -07:00
}
2020-09-16 08:00:44 +01:00
if ( sp - > hdr . securityIndex ! = RXRPC_SECURITY_NONE & &
! rx - > securities ) {
2022-10-06 21:45:42 +01:00
rxrpc_direct_abort ( skb , rxrpc_abort_no_service_key ,
sec - > no_key_abort , - EKEYREJECTED ) ;
2020-09-16 08:00:44 +01:00
return NULL ;
2007-04-26 15:48:28 -07:00
}
2020-09-16 08:00:44 +01:00
return sec ;
}
/*
* Find the security key for a server connection .
*/
struct key * rxrpc_look_up_server_security ( struct rxrpc_connection * conn ,
struct sk_buff * skb ,
u32 kvno , u32 enctype )
{
struct rxrpc_skb_priv * sp = rxrpc_skb ( skb ) ;
struct rxrpc_sock * rx ;
struct key * key = ERR_PTR ( - EKEYREJECTED ) ;
key_ref_t kref = NULL ;
char kdesc [ 5 + 1 + 3 + 1 + 12 + 1 + 12 + 1 ] ;
int ret ;
_enter ( " " ) ;
if ( enctype )
sprintf ( kdesc , " %u:%u:%u:%u " ,
sp - > hdr . serviceId , sp - > hdr . securityIndex , kvno , enctype ) ;
else if ( kvno )
sprintf ( kdesc , " %u:%u:%u " ,
sp - > hdr . serviceId , sp - > hdr . securityIndex , kvno ) ;
else
sprintf ( kdesc , " %u:%u " ,
sp - > hdr . serviceId , sp - > hdr . securityIndex ) ;
rcu_read_lock ( ) ;
2022-10-19 13:49:02 +01:00
rx = rcu_dereference ( conn - > local - > service ) ;
2020-09-16 08:00:44 +01:00
if ( ! rx )
goto out ;
2007-04-26 15:48:28 -07:00
/* look through the service's keyring */
kref = keyring_search ( make_key_ref ( rx - > securities , 1UL ) ,
2019-06-26 21:02:32 +01:00
& key_type_rxrpc_s , kdesc , true ) ;
2007-04-26 15:48:28 -07:00
if ( IS_ERR ( kref ) ) {
2020-09-16 08:00:44 +01:00
key = ERR_CAST ( kref ) ;
goto out ;
}
key = key_ref_to_ptr ( kref ) ;
ret = key_validate ( key ) ;
if ( ret < 0 ) {
key_put ( key ) ;
key = ERR_PTR ( ret ) ;
goto out ;
2007-04-26 15:48:28 -07:00
}
2019-12-20 16:17:16 +00:00
out :
2020-09-16 08:00:44 +01:00
rcu_read_unlock ( ) ;
return key ;
2007-04-26 15:48:28 -07:00
}