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/module.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/types.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/xdr.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/svcsock.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sunrpc/svcauth.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hash.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RPCDBG_FACILITY RPCDBG_AUTH 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Table of authenticators 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct auth_ops svcauth_null; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct auth_ops svcauth_unix; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(authtab_lock); 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct auth_ops *authtab[RPC_AUTH_MAXFLAVOR] = { 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [0] = &svcauth_null, 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [1] = &svcauth_unix, 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 37d8ed029d6000ba2e2908d9286409e4833c091b4cAlexey Dobriyansvc_authenticate(struct svc_rqst *rqstp, __be32 *authp) 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rpc_authflavor_t flavor; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct auth_ops *aops; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *authp = rpc_auth_ok; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 447699431301b189fca7ccbb64fe54e5a5170f8497Alexey Dobriyan flavor = svc_getnl(&rqstp->rq_arg.head[0]); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk("svc: svc_authenticate (%d)\n", flavor); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&authtab_lock); 49f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches if (flavor >= RPC_AUTH_MAXFLAVOR || !(aops = authtab[flavor]) || 50f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches !try_module_get(aops->owner)) { 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *authp = rpc_autherr_badcred; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SVC_DENIED; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57a5cddc885b99458df963a75abbe0b40cbef56c48J. Bruce Fields rqstp->rq_auth_slack = 0; 58a5cddc885b99458df963a75abbe0b40cbef56c48J. Bruce Fields 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rqstp->rq_authop = aops; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return aops->accept(rqstp, authp); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6224c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_authenticate); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint svc_set_client(struct svc_rqst *rqstp) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rqstp->rq_authop->set_client(rqstp); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6824c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_set_client); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A request, which was authenticated, has now executed. 7159c51591a0ac7568824f541f57de967e88adaa07Michael Opdenacker * Time to finalise the credentials and verifier 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and release and resources 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint svc_authorise(struct svc_rqst *rqstp) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct auth_ops *aops = rqstp->rq_authop; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rv = 0; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rqstp->rq_authop = NULL; 80cca5172a7ec10dfdb0b787cd8e9d5b0b8f179793YOSHIFUJI Hideaki 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (aops) { 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = aops->release(rqstp); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module_put(aops->owner); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rv; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rv = -EINVAL; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&authtab_lock); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flavor < RPC_AUTH_MAXFLAVOR && authtab[flavor] == NULL) { 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds authtab[flavor] = aops; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = 0; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rv; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10024c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_auth_register); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssvc_auth_unregister(rpc_authflavor_t flavor) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&authtab_lock); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flavor < RPC_AUTH_MAXFLAVOR) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds authtab[flavor] = NULL; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&authtab_lock); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11024c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(svc_auth_unregister); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************************************** 113efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * 'auth_domains' are stored in a hash table indexed by name. 114efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * When the last reference to an 'auth_domain' is dropped, 115efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * the object is unhashed and freed. 116efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * If auth_domain_lookup fails to find an entry, it will return 117efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * it's second argument 'new'. If this is non-null, it will 118efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown * have been atomically linked into the table. 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DN_HASHBITS 6 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DN_HASHMAX (1<<DN_HASHBITS) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 124efc36aa5608f5717338747e152c23f2cfdb14697NeilBrownstatic struct hlist_head auth_domain_table[DN_HASHMAX]; 1256cfd76a26d9fe2ba54b9d496a48c1d9285e5c5edPeter Zijlstrastatic spinlock_t auth_domain_lock = 1266cfd76a26d9fe2ba54b9d496a48c1d9285e5c5edPeter Zijlstra __SPIN_LOCK_UNLOCKED(auth_domain_lock); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid auth_domain_put(struct auth_domain *dom) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 130efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) { 131efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown hlist_del(&dom->hash); 132efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown dom->flavour->domain_release(dom); 1330c7bb31db0e35d4b772fac452b722460ca368acfAkinobu Mita spin_unlock(&auth_domain_lock); 134efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13624c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(auth_domain_put); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct auth_domain * 139efc36aa5608f5717338747e152c23f2cfdb14697NeilBrownauth_domain_lookup(char *name, struct auth_domain *new) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 141efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown struct auth_domain *hp; 142efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown struct hlist_head *head; 143efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown 144efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown head = &auth_domain_table[hash_str(name, DN_HASHBITS)]; 145efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown 146efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown spin_lock(&auth_domain_lock); 147efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown 148b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin hlist_for_each_entry(hp, head, hash) { 149efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown if (strcmp(hp->name, name)==0) { 150efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown kref_get(&hp->ref); 151efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown spin_unlock(&auth_domain_lock); 152efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown return hp; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 155d6740df98e12a8e49ef3a699dcc1e2913f22c51bNeil Brown if (new) 156efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown hlist_add_head(&new->hash, head); 157efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown spin_unlock(&auth_domain_lock); 158efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown return new; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16024c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(auth_domain_lookup); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct auth_domain *auth_domain_find(char *name) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 164efc36aa5608f5717338747e152c23f2cfdb14697NeilBrown return auth_domain_lookup(name, NULL); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16624c3767e41a6a59d32bb45abe899eb194e6bf1b8Trond MyklebustEXPORT_SYMBOL_GPL(auth_domain_find); 167