svcauth.c revision cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/net/sunrpc/svcauth.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The generic interface for RPC authentication on the server side. 5cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CHANGES 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 19-Apr-2000 Chris Evans - Security fix 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/types.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/xdr.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/svcsock.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/svcauth.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hash.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RPCDBG_FACILITY RPCDBG_AUTH 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Table of authenticators 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct auth_ops svcauth_null; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct auth_ops svcauth_unix; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(authtab_lock); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct auth_ops *authtab[RPC_AUTH_MAXFLAVOR] = { 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [0] = &svcauth_null, 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [1] = &svcauth_unix, 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 38d8ed029d6000ba2e2908d9286409e4833c091b4cAlexey Dobriyansvc_authenticate(struct svc_rqst *rqstp, __be32 *authp) 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpc_authflavor_t flavor; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct auth_ops *aops; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *authp = rpc_auth_ok; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 457699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan flavor = svc_getnl(&rqstp->rq_arg.head[0]); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("svc: svc_authenticate (%d)\n", flavor); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&authtab_lock); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flavor >= RPC_AUTH_MAXFLAVOR || !(aops = authtab[flavor]) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || !try_module_get(aops->owner)) { 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *authp = rpc_autherr_badcred; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SVC_DENIED; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rqstp->rq_authop = aops; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return aops->accept(rqstp, authp); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint svc_set_client(struct svc_rqst *rqstp) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rqstp->rq_authop->set_client(rqstp); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A request, which was authenticated, has now executed. 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Time to finalise the the credentials and verifier 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and release and resources 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint svc_authorise(struct svc_rqst *rqstp) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct auth_ops *aops = rqstp->rq_authop; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rv = 0; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rqstp->rq_authop = NULL; 77cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (aops) { 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = aops->release(rqstp); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module_put(aops->owner); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rv; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rv = -EINVAL; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&authtab_lock); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flavor < RPC_AUTH_MAXFLAVOR && authtab[flavor] == NULL) { 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds authtab[flavor] = aops; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = 0; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rv; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_auth_unregister(rpc_authflavor_t flavor) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&authtab_lock); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flavor < RPC_AUTH_MAXFLAVOR) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds authtab[flavor] = NULL; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(svc_auth_unregister); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************************************** 109efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * 'auth_domains' are stored in a hash table indexed by name. 110efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * When the last reference to an 'auth_domain' is dropped, 111efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * the object is unhashed and freed. 112efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * If auth_domain_lookup fails to find an entry, it will return 113efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * it's second argument 'new'. If this is non-null, it will 114efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * have been atomically linked into the table. 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DN_HASHBITS 6 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DN_HASHMAX (1<<DN_HASHBITS) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DN_HASHMASK (DN_HASHMAX-1) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121efc36aa5608f5717338747e152c23f2cfdb14697NeilBrownstatic struct hlist_head auth_domain_table[DN_HASHMAX]; 1226cfd76a26d9fe2ba54b9d496a48c1d9285e5c5edPeter Zijlstrastatic spinlock_t auth_domain_lock = 1236cfd76a26d9fe2ba54b9d496a48c1d9285e5c5edPeter Zijlstra __SPIN_LOCK_UNLOCKED(auth_domain_lock); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid auth_domain_put(struct auth_domain *dom) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 127efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) { 128efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown hlist_del(&dom->hash); 129efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown dom->flavour->domain_release(dom); 1300c7bb31db0e35d4b772fac452b722460ca368acfAkinobu Mita spin_unlock(&auth_domain_lock); 131efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown } 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct auth_domain * 135efc36aa5608f5717338747e152c23f2cfdb14697NeilBrownauth_domain_lookup(char *name, struct auth_domain *new) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 137efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown struct auth_domain *hp; 138efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown struct hlist_head *head; 139efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown struct hlist_node *np; 140efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown 141efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown head = &auth_domain_table[hash_str(name, DN_HASHBITS)]; 142efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown 143efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown spin_lock(&auth_domain_lock); 144efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown 145efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown hlist_for_each_entry(hp, np, head, hash) { 146efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown if (strcmp(hp->name, name)==0) { 147efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown kref_get(&hp->ref); 148efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown spin_unlock(&auth_domain_lock); 149efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown return hp; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 152d6740df98e12a8e49ef3a699dcc1e2913f22c51bNeil Brown if (new) 153efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown hlist_add_head(&new->hash, head); 154efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown spin_unlock(&auth_domain_lock); 155efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown return new; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct auth_domain *auth_domain_find(char *name) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 160efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown return auth_domain_lookup(name, NULL); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 162