2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* linux/include/linux/sunrpc/svcauth.h
|
|
|
|
*
|
|
|
|
* RPC server-side authentication stuff.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LINUX_SUNRPC_SVCAUTH_H_
|
|
|
|
#define _LINUX_SUNRPC_SVCAUTH_H_
|
|
|
|
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/sunrpc/msg_prot.h>
|
|
|
|
#include <linux/sunrpc/cache.h>
|
|
|
|
#include <linux/hash.h>
|
|
|
|
|
|
|
|
#define SVC_CRED_NGROUPS 32
|
|
|
|
struct svc_cred {
|
|
|
|
uid_t cr_uid;
|
|
|
|
gid_t cr_gid;
|
|
|
|
struct group_info *cr_group_info;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct svc_rqst; /* forward decl */
|
2008-01-18 22:50:56 +08:00
|
|
|
struct in6_addr;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Authentication is done in the context of a domain.
|
|
|
|
*
|
|
|
|
* Currently, the nfs server uses the auth_domain to stand
|
|
|
|
* for the "client" listed in /etc/exports.
|
|
|
|
*
|
|
|
|
* More generally, a domain might represent a group of clients using
|
|
|
|
* a common mechanism for authentication and having a common mapping
|
|
|
|
* between local identity (uid) and network identity. All clients
|
|
|
|
* in a domain have similar general access rights. Each domain can
|
|
|
|
* contain multiple principals which will have different specific right
|
|
|
|
* based on normal Discretionary Access Control.
|
|
|
|
*
|
|
|
|
* A domain is created by an authentication flavour module based on name
|
|
|
|
* only. Userspace then fills in detail on demand.
|
|
|
|
*
|
|
|
|
* In the case of auth_unix and auth_null, the auth_domain is also
|
|
|
|
* associated with entries in another cache representing the mapping
|
|
|
|
* of ip addresses to the given client.
|
|
|
|
*/
|
|
|
|
struct auth_domain {
|
2006-03-27 17:14:59 +08:00
|
|
|
struct kref ref;
|
|
|
|
struct hlist_node hash;
|
2005-04-17 06:20:36 +08:00
|
|
|
char *name;
|
2006-03-27 17:14:59 +08:00
|
|
|
struct auth_ops *flavour;
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Each authentication flavour registers an auth_ops
|
|
|
|
* structure.
|
|
|
|
* name is simply the name.
|
|
|
|
* flavour gives the auth flavour. It determines where the flavour is registered
|
|
|
|
* accept() is given a request and should verify it.
|
|
|
|
* It should inspect the authenticator and verifier, and possibly the data.
|
|
|
|
* If there is a problem with the authentication *authp should be set.
|
|
|
|
* The return value of accept() can indicate:
|
|
|
|
* OK - authorised. client and credential are set in rqstp.
|
|
|
|
* reqbuf points to arguments
|
|
|
|
* resbuf points to good place for results. verfier
|
|
|
|
* is (probably) already in place. Certainly space is
|
|
|
|
* reserved for it.
|
|
|
|
* DROP - simply drop the request. It may have been deferred
|
|
|
|
* GARBAGE - rpc garbage_args error
|
|
|
|
* SYSERR - rpc system_err error
|
|
|
|
* DENIED - authp holds reason for denial.
|
|
|
|
* COMPLETE - the reply is encoded already and ready to be sent; no
|
|
|
|
* further processing is necessary. (This is used for processing
|
|
|
|
* null procedure calls which are used to set up encryption
|
|
|
|
* contexts.)
|
|
|
|
*
|
|
|
|
* accept is passed the proc number so that it can accept NULL rpc requests
|
|
|
|
* even if it cannot authenticate the client (as is sometimes appropriate).
|
|
|
|
*
|
|
|
|
* release() is given a request after the procedure has been run.
|
|
|
|
* It should sign/encrypt the results if needed
|
|
|
|
* It should return:
|
|
|
|
* OK - the resbuf is ready to be sent
|
|
|
|
* DROP - the reply should be quitely dropped
|
|
|
|
* DENIED - authp holds a reason for MSG_DENIED
|
|
|
|
* SYSERR - rpc system_err
|
|
|
|
*
|
|
|
|
* domain_release()
|
|
|
|
* This call releases a domain.
|
2006-03-27 17:14:59 +08:00
|
|
|
* set_client()
|
|
|
|
* Givens a pending request (struct svc_rqst), finds and assigns
|
|
|
|
* an appropriate 'auth_domain' as the client.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
struct auth_ops {
|
|
|
|
char * name;
|
|
|
|
struct module *owner;
|
|
|
|
int flavour;
|
2006-09-27 13:29:38 +08:00
|
|
|
int (*accept)(struct svc_rqst *rq, __be32 *authp);
|
2005-04-17 06:20:36 +08:00
|
|
|
int (*release)(struct svc_rqst *rq);
|
|
|
|
void (*domain_release)(struct auth_domain *);
|
|
|
|
int (*set_client)(struct svc_rqst *rq);
|
|
|
|
};
|
|
|
|
|
|
|
|
#define SVC_GARBAGE 1
|
|
|
|
#define SVC_SYSERR 2
|
|
|
|
#define SVC_VALID 3
|
|
|
|
#define SVC_NEGATIVE 4
|
|
|
|
#define SVC_OK 5
|
|
|
|
#define SVC_DROP 6
|
|
|
|
#define SVC_DENIED 7
|
|
|
|
#define SVC_PENDING 8
|
|
|
|
#define SVC_COMPLETE 9
|
|
|
|
|
|
|
|
|
2006-09-27 13:29:38 +08:00
|
|
|
extern int svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
|
2005-04-17 06:20:36 +08:00
|
|
|
extern int svc_authorise(struct svc_rqst *rqstp);
|
|
|
|
extern int svc_set_client(struct svc_rqst *rqstp);
|
|
|
|
extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
|
|
|
|
extern void svc_auth_unregister(rpc_authflavor_t flavor);
|
|
|
|
|
|
|
|
extern struct auth_domain *unix_domain_find(char *name);
|
|
|
|
extern void auth_domain_put(struct auth_domain *item);
|
2008-01-18 22:50:56 +08:00
|
|
|
extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
|
2006-03-27 17:14:59 +08:00
|
|
|
extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
|
2005-04-17 06:20:36 +08:00
|
|
|
extern struct auth_domain *auth_domain_find(char *name);
|
2008-01-18 22:50:56 +08:00
|
|
|
extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
|
2005-04-17 06:20:36 +08:00
|
|
|
extern int auth_unix_forget_old(struct auth_domain *dom);
|
|
|
|
extern void svcauth_unix_purge(void);
|
2006-10-04 17:15:50 +08:00
|
|
|
extern void svcauth_unix_info_release(void *);
|
knfsd: nfsd: set rq_client to ip-address-determined-domain
We want it to be possible for users to restrict exports both by IP address and
by pseudoflavor. The pseudoflavor information has previously been passed
using special auth_domains stored in the rq_client field. After the preceding
patch that stored the pseudoflavor in rq_pflavor, that's now superfluous; so
now we use rq_client for the ip information, as auth_null and auth_unix do.
However, we keep around the special auth_domain in the rq_gssclient field for
backwards compatibility purposes, so we can still do upcalls using the old
"gss/pseudoflavor" auth_domain if upcalls using the unix domain to give us an
appropriate export. This allows us to continue supporting old mountd.
In fact, for this first patch, we always use the "gss/pseudoflavor"
auth_domain (and only it) if it is available; thus rq_client is ignored in the
auth_gss case, and this patch on its own makes no change in behavior; that
will be left to later patches.
Note on idmap: I'm almost tempted to just replace the auth_domain in the idmap
upcall by a dummy value--no version of idmapd has ever used it, and it's
unlikely anyone really wants to perform idmapping differently depending on the
where the client is (they may want to perform *credential* mapping
differently, but that's a different matter--the idmapper just handles id's
used in getattr and setattr). But I'm updating the idmapd code anyway, just
out of general backwards-compatibility paranoia.
Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-17 19:04:46 +08:00
|
|
|
extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static inline unsigned long hash_str(char *name, int bits)
|
|
|
|
{
|
|
|
|
unsigned long hash = 0;
|
|
|
|
unsigned long l = 0;
|
|
|
|
int len = 0;
|
|
|
|
unsigned char c;
|
|
|
|
do {
|
|
|
|
if (unlikely(!(c = *name++))) {
|
|
|
|
c = (char)len; len = -1;
|
|
|
|
}
|
|
|
|
l = (l << 8) | c;
|
|
|
|
len++;
|
|
|
|
if ((len & (BITS_PER_LONG/8-1))==0)
|
|
|
|
hash = hash_long(hash^l, BITS_PER_LONG);
|
|
|
|
} while (len);
|
|
|
|
return hash >> (BITS_PER_LONG - bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned long hash_mem(char *buf, int length, int bits)
|
|
|
|
{
|
|
|
|
unsigned long hash = 0;
|
|
|
|
unsigned long l = 0;
|
|
|
|
int len = 0;
|
|
|
|
unsigned char c;
|
|
|
|
do {
|
|
|
|
if (len == length) {
|
|
|
|
c = (char)len; len = -1;
|
|
|
|
} else
|
|
|
|
c = *buf++;
|
|
|
|
l = (l << 8) | c;
|
|
|
|
len++;
|
|
|
|
if ((len & (BITS_PER_LONG/8-1))==0)
|
|
|
|
hash = hash_long(hash^l, BITS_PER_LONG);
|
|
|
|
} while (len);
|
|
|
|
return hash >> (BITS_PER_LONG - bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
|
|
|
|
#endif /* _LINUX_SUNRPC_SVCAUTH_H_ */
|