2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2007-04-27 02:48:28 +04: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 05:17:35 +04:00
# include <keys/rxrpc-type.h>
2007-04-27 02:48:28 +04:00
# include "ar-internal.h"
2016-04-07 19:23:51 +03:00
static const struct rxrpc_security * rxrpc_security_types [ ] = {
2016-04-07 19:23:58 +03:00
[ RXRPC_SECURITY_NONE ] = & rxrpc_no_security ,
2016-04-07 19:23:51 +03:00
# ifdef CONFIG_RXKAD
[ RXRPC_SECURITY_RXKAD ] = & rxkad ,
# endif
} ;
2007-04-27 02:48:28 +04:00
2016-04-07 19:23:51 +03:00
int __init rxrpc_init_security ( void )
2007-04-27 02:48:28 +04:00
{
2016-04-07 19:23:51 +03:00
int i , ret ;
2007-04-27 02:48:28 +04:00
2016-04-07 19:23:51 +03: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-27 02:48:28 +04:00
}
}
2016-04-07 19:23:51 +03:00
return 0 ;
failed :
for ( i - - ; i > = 0 ; i - - )
if ( rxrpc_security_types [ i ] )
rxrpc_security_types [ i ] - > exit ( ) ;
return ret ;
2007-04-27 02:48:28 +04:00
}
2016-04-07 19:23:51 +03:00
void rxrpc_exit_security ( void )
2007-04-27 02:48:28 +04:00
{
2016-04-07 19:23:51 +03:00
int i ;
2007-04-27 02:48:28 +04:00
2016-04-07 19:23:51 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( rxrpc_security_types ) ; i + + )
if ( rxrpc_security_types [ i ] )
rxrpc_security_types [ i ] - > exit ( ) ;
2007-04-27 02:48:28 +04:00
}
2016-04-07 19:23:51 +03:00
/*
* look up an rxrpc security module
2007-04-27 02:48:28 +04:00
*/
2016-04-07 19:23:51 +03:00
static const struct rxrpc_security * rxrpc_security_lookup ( u8 security_index )
2007-04-27 02:48:28 +04:00
{
2016-04-07 19:23:51 +03:00
if ( security_index > = ARRAY_SIZE ( rxrpc_security_types ) )
return NULL ;
return rxrpc_security_types [ security_index ] ;
2007-04-27 02:48:28 +04:00
}
/*
* initialise the security on a client connection
*/
int rxrpc_init_client_conn_security ( struct rxrpc_connection * conn )
{
2016-04-07 19:23:51 +03:00
const struct rxrpc_security * sec ;
2009-09-14 05:17:35 +04:00
struct rxrpc_key_token * token ;
2016-04-04 16:00:36 +03:00
struct key * key = conn - > params . key ;
2007-04-27 02:48:28 +04:00
int ret ;
_enter ( " {%d},{%x} " , conn - > debug_id , key_serial ( key ) ) ;
if ( ! key )
return 0 ;
ret = key_validate ( key ) ;
if ( ret < 0 )
return ret ;
2015-10-21 16:04:48 +03:00
token = key - > payload . data [ 0 ] ;
if ( ! token )
2009-09-14 05:17:35 +04:00
return - EKEYREJECTED ;
sec = rxrpc_security_lookup ( token - > security_index ) ;
2007-04-27 02:48:28 +04:00
if ( ! sec )
return - EKEYREJECTED ;
conn - > security = sec ;
ret = conn - > security - > init_connection_security ( conn ) ;
if ( ret < 0 ) {
2016-04-07 19:23:58 +03:00
conn - > security = & rxrpc_no_security ;
2007-04-27 02:48:28 +04:00
return ret ;
}
_leave ( " = 0 " ) ;
return 0 ;
}
/*
2019-12-20 19:17:16 +03:00
* Find the security key for a server connection .
2007-04-27 02:48:28 +04:00
*/
2019-12-20 19:17:16 +03:00
bool rxrpc_look_up_server_security ( struct rxrpc_local * local , struct rxrpc_sock * rx ,
const struct rxrpc_security * * _sec ,
struct key * * _key ,
struct sk_buff * skb )
2007-04-27 02:48:28 +04:00
{
2016-04-07 19:23:51 +03:00
const struct rxrpc_security * sec ;
2019-12-20 19:17:16 +03:00
struct rxrpc_skb_priv * sp = rxrpc_skb ( skb ) ;
key_ref_t kref = NULL ;
2016-03-04 18:56:19 +03:00
char kdesc [ 5 + 1 + 3 + 1 ] ;
2007-04-27 02:48:28 +04:00
_enter ( " " ) ;
2019-12-20 19:17:16 +03:00
sprintf ( kdesc , " %u:%u " , sp - > hdr . serviceId , sp - > hdr . securityIndex ) ;
2007-04-27 02:48:28 +04:00
2019-12-20 19:17:16 +03:00
sec = rxrpc_security_lookup ( sp - > hdr . securityIndex ) ;
2007-04-27 02:48:28 +04:00
if ( ! sec ) {
2019-12-20 19:17:16 +03:00
trace_rxrpc_abort ( 0 , " SVS " ,
sp - > hdr . cid , sp - > hdr . callNumber , sp - > hdr . seq ,
RX_INVALID_OPERATION , EKEYREJECTED ) ;
skb - > mark = RXRPC_SKB_MARK_REJECT_ABORT ;
skb - > priority = RX_INVALID_OPERATION ;
return false ;
2007-04-27 02:48:28 +04:00
}
2019-12-20 19:17:16 +03:00
if ( sp - > hdr . securityIndex = = RXRPC_SECURITY_NONE )
goto out ;
2007-04-27 02:48:28 +04:00
if ( ! rx - > securities ) {
2019-12-20 19:17:16 +03:00
trace_rxrpc_abort ( 0 , " SVR " ,
sp - > hdr . cid , sp - > hdr . callNumber , sp - > hdr . seq ,
RX_INVALID_OPERATION , EKEYREJECTED ) ;
skb - > mark = RXRPC_SKB_MARK_REJECT_ABORT ;
skb - > priority = RX_INVALID_OPERATION ;
return false ;
2007-04-27 02:48:28 +04:00
}
/* look through the service's keyring */
kref = keyring_search ( make_key_ref ( rx - > securities , 1UL ) ,
2019-06-26 23:02:32 +03:00
& key_type_rxrpc_s , kdesc , true ) ;
2007-04-27 02:48:28 +04:00
if ( IS_ERR ( kref ) ) {
2019-12-20 19:17:16 +03:00
trace_rxrpc_abort ( 0 , " SVK " ,
sp - > hdr . cid , sp - > hdr . callNumber , sp - > hdr . seq ,
sec - > no_key_abort , EKEYREJECTED ) ;
skb - > mark = RXRPC_SKB_MARK_REJECT_ABORT ;
skb - > priority = sec - > no_key_abort ;
return false ;
2007-04-27 02:48:28 +04:00
}
2019-12-20 19:17:16 +03:00
out :
* _sec = sec ;
* _key = key_ref_to_ptr ( kref ) ;
return true ;
2007-04-27 02:48:28 +04:00
}