2005-04-17 02:20:36 +04:00
/*
* linux / net / sunrpc / svcauth . c
*
* The generic interface for RPC authentication on the server side .
2007-02-10 02:38:13 +03:00
*
2005-04-17 02:20:36 +04:00
* Copyright ( C ) 1995 , 1996 Olaf Kirch < okir @ monad . swb . de >
*
* CHANGES
* 19 - Apr - 2000 Chris Evans - Security fix
*/
# include <linux/types.h>
# include <linux/module.h>
# include <linux/sunrpc/types.h>
# include <linux/sunrpc/xdr.h>
# include <linux/sunrpc/svcsock.h>
# include <linux/sunrpc/svcauth.h>
# include <linux/err.h>
# include <linux/hash.h>
# define RPCDBG_FACILITY RPCDBG_AUTH
/*
* Table of authenticators
*/
extern struct auth_ops svcauth_null ;
extern struct auth_ops svcauth_unix ;
static DEFINE_SPINLOCK ( authtab_lock ) ;
static struct auth_ops * authtab [ RPC_AUTH_MAXFLAVOR ] = {
[ 0 ] = & svcauth_null ,
[ 1 ] = & svcauth_unix ,
} ;
int
2006-09-27 09:29:38 +04:00
svc_authenticate ( struct svc_rqst * rqstp , __be32 * authp )
2005-04-17 02:20:36 +04:00
{
rpc_authflavor_t flavor ;
struct auth_ops * aops ;
* authp = rpc_auth_ok ;
2006-09-27 09:28:46 +04:00
flavor = svc_getnl ( & rqstp - > rq_arg . head [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: svc_authenticate (%d) \n " , flavor ) ;
spin_lock ( & authtab_lock ) ;
2009-11-30 03:55:45 +03:00
if ( flavor > = RPC_AUTH_MAXFLAVOR | | ! ( aops = authtab [ flavor ] ) | |
! try_module_get ( aops - > owner ) ) {
2005-04-17 02:20:36 +04:00
spin_unlock ( & authtab_lock ) ;
* authp = rpc_autherr_badcred ;
return SVC_DENIED ;
}
spin_unlock ( & authtab_lock ) ;
rqstp - > rq_authop = aops ;
return aops - > accept ( rqstp , authp ) ;
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( svc_authenticate ) ;
2005-04-17 02:20:36 +04:00
int svc_set_client ( struct svc_rqst * rqstp )
{
return rqstp - > rq_authop - > set_client ( rqstp ) ;
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( svc_set_client ) ;
2005-04-17 02:20:36 +04:00
/* A request, which was authenticated, has now executed.
2007-05-09 10:57:56 +04:00
* Time to finalise the credentials and verifier
2005-04-17 02:20:36 +04:00
* and release and resources
*/
int svc_authorise ( struct svc_rqst * rqstp )
{
struct auth_ops * aops = rqstp - > rq_authop ;
int rv = 0 ;
rqstp - > rq_authop = NULL ;
2007-02-10 02:38:13 +03:00
2005-04-17 02:20:36 +04:00
if ( aops ) {
rv = aops - > release ( rqstp ) ;
module_put ( aops - > owner ) ;
}
return rv ;
}
int
svc_auth_register ( rpc_authflavor_t flavor , struct auth_ops * aops )
{
int rv = - EINVAL ;
spin_lock ( & authtab_lock ) ;
if ( flavor < RPC_AUTH_MAXFLAVOR & & authtab [ flavor ] = = NULL ) {
authtab [ flavor ] = aops ;
rv = 0 ;
}
spin_unlock ( & authtab_lock ) ;
return rv ;
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( svc_auth_register ) ;
2005-04-17 02:20:36 +04:00
void
svc_auth_unregister ( rpc_authflavor_t flavor )
{
spin_lock ( & authtab_lock ) ;
if ( flavor < RPC_AUTH_MAXFLAVOR )
authtab [ flavor ] = NULL ;
spin_unlock ( & authtab_lock ) ;
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( svc_auth_unregister ) ;
2005-04-17 02:20:36 +04:00
/**************************************************
2006-03-27 13:14:59 +04:00
* ' auth_domains ' are stored in a hash table indexed by name .
* When the last reference to an ' auth_domain ' is dropped ,
* the object is unhashed and freed .
* If auth_domain_lookup fails to find an entry , it will return
* it ' s second argument ' new ' . If this is non - null , it will
* have been atomically linked into the table .
2005-04-17 02:20:36 +04:00
*/
# define DN_HASHBITS 6
# define DN_HASHMAX (1<<DN_HASHBITS)
2006-03-27 13:14:59 +04:00
static struct hlist_head auth_domain_table [ DN_HASHMAX ] ;
2006-12-07 07:37:22 +03:00
static spinlock_t auth_domain_lock =
__SPIN_LOCK_UNLOCKED ( auth_domain_lock ) ;
2005-04-17 02:20:36 +04:00
void auth_domain_put ( struct auth_domain * dom )
{
2006-03-27 13:14:59 +04:00
if ( atomic_dec_and_lock ( & dom - > ref . refcount , & auth_domain_lock ) ) {
hlist_del ( & dom - > hash ) ;
dom - > flavour - > domain_release ( dom ) ;
2006-11-06 10:52:13 +03:00
spin_unlock ( & auth_domain_lock ) ;
2006-03-27 13:14:59 +04:00
}
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( auth_domain_put ) ;
2005-04-17 02:20:36 +04:00
struct auth_domain *
2006-03-27 13:14:59 +04:00
auth_domain_lookup ( char * name , struct auth_domain * new )
2005-04-17 02:20:36 +04:00
{
2006-03-27 13:14:59 +04:00
struct auth_domain * hp ;
struct hlist_head * head ;
struct hlist_node * np ;
head = & auth_domain_table [ hash_str ( name , DN_HASHBITS ) ] ;
spin_lock ( & auth_domain_lock ) ;
hlist_for_each_entry ( hp , np , head , hash ) {
if ( strcmp ( hp - > name , name ) = = 0 ) {
kref_get ( & hp - > ref ) ;
spin_unlock ( & auth_domain_lock ) ;
return hp ;
2005-04-17 02:20:36 +04:00
}
}
2006-10-30 09:46:45 +03:00
if ( new )
2006-03-27 13:14:59 +04:00
hlist_add_head ( & new - > hash , head ) ;
spin_unlock ( & auth_domain_lock ) ;
return new ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( auth_domain_lookup ) ;
2005-04-17 02:20:36 +04:00
struct auth_domain * auth_domain_find ( char * name )
{
2006-03-27 13:14:59 +04:00
return auth_domain_lookup ( name , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( auth_domain_find ) ;