⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svcauth_unix.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	spin_lock(&svsk->sk_lock);	if (svsk->sk_sock->type == SOCK_STREAM &&	    svsk->sk_info_authunix == NULL) {		/* newly cached, keep the reference */		svsk->sk_info_authunix = ipm;		ipm = NULL;	}	spin_unlock(&svsk->sk_lock);	if (ipm)		cache_put(&ipm->h, &ip_map_cache);}voidsvcauth_unix_info_release(void *info){	struct ip_map *ipm = info;	cache_put(&ipm->h, &ip_map_cache);}/**************************************************************************** * auth.unix.gid cache * simple cache to map a UID to a list of GIDs * because AUTH_UNIX aka AUTH_SYS has a max of 16 */#define	GID_HASHBITS	8#define	GID_HASHMAX	(1<<GID_HASHBITS)#define	GID_HASHMASK	(GID_HASHMAX - 1)struct unix_gid {	struct cache_head	h;	uid_t			uid;	struct group_info	*gi;};static struct cache_head	*gid_table[GID_HASHMAX];static void unix_gid_put(struct kref *kref){	struct cache_head *item = container_of(kref, struct cache_head, ref);	struct unix_gid *ug = container_of(item, struct unix_gid, h);	if (test_bit(CACHE_VALID, &item->flags) &&	    !test_bit(CACHE_NEGATIVE, &item->flags))		put_group_info(ug->gi);	kfree(ug);}static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew){	struct unix_gid *orig = container_of(corig, struct unix_gid, h);	struct unix_gid *new = container_of(cnew, struct unix_gid, h);	return orig->uid == new->uid;}static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem){	struct unix_gid *new = container_of(cnew, struct unix_gid, h);	struct unix_gid *item = container_of(citem, struct unix_gid, h);	new->uid = item->uid;}static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem){	struct unix_gid *new = container_of(cnew, struct unix_gid, h);	struct unix_gid *item = container_of(citem, struct unix_gid, h);	get_group_info(item->gi);	new->gi = item->gi;}static struct cache_head *unix_gid_alloc(void){	struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);	if (g)		return &g->h;	else		return NULL;}static void unix_gid_request(struct cache_detail *cd,			     struct cache_head *h,			     char **bpp, int *blen){	char tuid[20];	struct unix_gid *ug = container_of(h, struct unix_gid, h);	snprintf(tuid, 20, "%u", ug->uid);	qword_add(bpp, blen, tuid);	(*bpp)[-1] = '\n';}static struct unix_gid *unix_gid_lookup(uid_t uid);extern struct cache_detail unix_gid_cache;static int unix_gid_parse(struct cache_detail *cd,			char *mesg, int mlen){	/* uid expiry Ngid gid0 gid1 ... gidN-1 */	int uid;	int gids;	int rv;	int i;	int err;	time_t expiry;	struct unix_gid ug, *ugp;	if (mlen <= 0 || mesg[mlen-1] != '\n')		return -EINVAL;	mesg[mlen-1] = 0;	rv = get_int(&mesg, &uid);	if (rv)		return -EINVAL;	ug.uid = uid;	expiry = get_expiry(&mesg);	if (expiry == 0)		return -EINVAL;	rv = get_int(&mesg, &gids);	if (rv || gids < 0 || gids > 8192)		return -EINVAL;	ug.gi = groups_alloc(gids);	if (!ug.gi)		return -ENOMEM;	for (i = 0 ; i < gids ; i++) {		int gid;		rv = get_int(&mesg, &gid);		err = -EINVAL;		if (rv)			goto out;		GROUP_AT(ug.gi, i) = gid;	}	ugp = unix_gid_lookup(uid);	if (ugp) {		struct cache_head *ch;		ug.h.flags = 0;		ug.h.expiry_time = expiry;		ch = sunrpc_cache_update(&unix_gid_cache,					 &ug.h, &ugp->h,					 hash_long(uid, GID_HASHBITS));		if (!ch)			err = -ENOMEM;		else {			err = 0;			cache_put(ch, &unix_gid_cache);		}	} else		err = -ENOMEM; out:	if (ug.gi)		put_group_info(ug.gi);	return err;}static int unix_gid_show(struct seq_file *m,			 struct cache_detail *cd,			 struct cache_head *h){	struct unix_gid *ug;	int i;	int glen;	if (h == NULL) {		seq_puts(m, "#uid cnt: gids...\n");		return 0;	}	ug = container_of(h, struct unix_gid, h);	if (test_bit(CACHE_VALID, &h->flags) &&	    !test_bit(CACHE_NEGATIVE, &h->flags))		glen = ug->gi->ngroups;	else		glen = 0;	seq_printf(m, "%d %d:", ug->uid, glen);	for (i = 0; i < glen; i++)		seq_printf(m, " %d", GROUP_AT(ug->gi, i));	seq_printf(m, "\n");	return 0;}struct cache_detail unix_gid_cache = {	.owner		= THIS_MODULE,	.hash_size	= GID_HASHMAX,	.hash_table	= gid_table,	.name		= "auth.unix.gid",	.cache_put	= unix_gid_put,	.cache_request	= unix_gid_request,	.cache_parse	= unix_gid_parse,	.cache_show	= unix_gid_show,	.match		= unix_gid_match,	.init		= unix_gid_init,	.update		= unix_gid_update,	.alloc		= unix_gid_alloc,};static struct unix_gid *unix_gid_lookup(uid_t uid){	struct unix_gid ug;	struct cache_head *ch;	ug.uid = uid;	ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h,				 hash_long(uid, GID_HASHBITS));	if (ch)		return container_of(ch, struct unix_gid, h);	else		return NULL;}static int unix_gid_find(uid_t uid, struct group_info **gip,			 struct svc_rqst *rqstp){	struct unix_gid *ug = unix_gid_lookup(uid);	if (!ug)		return -EAGAIN;	switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {	case -ENOENT:		*gip = NULL;		return 0;	case 0:		*gip = ug->gi;		get_group_info(*gip);		return 0;	default:		return -EAGAIN;	}}intsvcauth_unix_set_client(struct svc_rqst *rqstp){	struct sockaddr_in *sin = svc_addr_in(rqstp);	struct ip_map *ipm;	rqstp->rq_client = NULL;	if (rqstp->rq_proc == 0)		return SVC_OK;	ipm = ip_map_cached_get(rqstp);	if (ipm == NULL)		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,				    sin->sin_addr);	if (ipm == NULL)		return SVC_DENIED;	switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {		default:			BUG();		case -EAGAIN:		case -ETIMEDOUT:			return SVC_DROP;		case -ENOENT:			return SVC_DENIED;		case 0:			rqstp->rq_client = &ipm->m_client->h;			kref_get(&rqstp->rq_client->ref);			ip_map_cached_put(rqstp, ipm);			break;	}	return SVC_OK;}EXPORT_SYMBOL(svcauth_unix_set_client);static intsvcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp){	struct kvec	*argv = &rqstp->rq_arg.head[0];	struct kvec	*resv = &rqstp->rq_res.head[0];	struct svc_cred	*cred = &rqstp->rq_cred;	cred->cr_group_info = NULL;	rqstp->rq_client = NULL;	if (argv->iov_len < 3*4)		return SVC_GARBAGE;	if (svc_getu32(argv) != 0) {		dprintk("svc: bad null cred\n");		*authp = rpc_autherr_badcred;		return SVC_DENIED;	}	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {		dprintk("svc: bad null verf\n");		*authp = rpc_autherr_badverf;		return SVC_DENIED;	}	/* Signal that mapping to nobody uid/gid is required */	cred->cr_uid = (uid_t) -1;	cred->cr_gid = (gid_t) -1;	cred->cr_group_info = groups_alloc(0);	if (cred->cr_group_info == NULL)		return SVC_DROP; /* kmalloc failure - client must retry */	/* Put NULL verifier */	svc_putnl(resv, RPC_AUTH_NULL);	svc_putnl(resv, 0);	rqstp->rq_flavor = RPC_AUTH_NULL;	return SVC_OK;}static intsvcauth_null_release(struct svc_rqst *rqstp){	if (rqstp->rq_client)		auth_domain_put(rqstp->rq_client);	rqstp->rq_client = NULL;	if (rqstp->rq_cred.cr_group_info)		put_group_info(rqstp->rq_cred.cr_group_info);	rqstp->rq_cred.cr_group_info = NULL;	return 0; /* don't drop */}struct auth_ops svcauth_null = {	.name		= "null",	.owner		= THIS_MODULE,	.flavour	= RPC_AUTH_NULL,	.accept 	= svcauth_null_accept,	.release	= svcauth_null_release,	.set_client	= svcauth_unix_set_client,};static intsvcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp){	struct kvec	*argv = &rqstp->rq_arg.head[0];	struct kvec	*resv = &rqstp->rq_res.head[0];	struct svc_cred	*cred = &rqstp->rq_cred;	u32		slen, i;	int		len   = argv->iov_len;	cred->cr_group_info = NULL;	rqstp->rq_client = NULL;	if ((len -= 3*4) < 0)		return SVC_GARBAGE;	svc_getu32(argv);			/* length */	svc_getu32(argv);			/* time stamp */	slen = XDR_QUADLEN(svc_getnl(argv));	/* machname length */	if (slen > 64 || (len -= (slen + 3)*4) < 0)		goto badcred;	argv->iov_base = (void*)((__be32*)argv->iov_base + slen);	/* skip machname */	argv->iov_len -= slen*4;	cred->cr_uid = svc_getnl(argv);		/* uid */	cred->cr_gid = svc_getnl(argv);		/* gid */	slen = svc_getnl(argv);			/* gids length */	if (slen > 16 || (len -= (slen + 2)*4) < 0)		goto badcred;	if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)	    == -EAGAIN)		return SVC_DROP;	if (cred->cr_group_info == NULL) {		cred->cr_group_info = groups_alloc(slen);		if (cred->cr_group_info == NULL)			return SVC_DROP;		for (i = 0; i < slen; i++)			GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);	} else {		for (i = 0; i < slen ; i++)			svc_getnl(argv);	}	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {		*authp = rpc_autherr_badverf;		return SVC_DENIED;	}	/* Put NULL verifier */	svc_putnl(resv, RPC_AUTH_NULL);	svc_putnl(resv, 0);	rqstp->rq_flavor = RPC_AUTH_UNIX;	return SVC_OK;badcred:	*authp = rpc_autherr_badcred;	return SVC_DENIED;}static intsvcauth_unix_release(struct svc_rqst *rqstp){	/* Verifier (such as it is) is already in place.	 */	if (rqstp->rq_client)		auth_domain_put(rqstp->rq_client);	rqstp->rq_client = NULL;	if (rqstp->rq_cred.cr_group_info)		put_group_info(rqstp->rq_cred.cr_group_info);	rqstp->rq_cred.cr_group_info = NULL;	return 0;}struct auth_ops svcauth_unix = {	.name		= "unix",	.owner		= THIS_MODULE,	.flavour	= RPC_AUTH_UNIX,	.accept 	= svcauth_unix_accept,	.release	= svcauth_unix_release,	.domain_release	= svcauth_unix_domain_release,	.set_client	= svcauth_unix_set_client,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -