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

📄 auth_gss.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct rpc_cred *cred = task->tk_msg.rpc_cred;	struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,			struct gss_auth, rpc_auth);	struct gss_cred *gss_cred = container_of(cred,			struct gss_cred, gc_base);	struct gss_upcall_msg *gss_msg;	int err = 0;	dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid);	gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);	if (IS_ERR(gss_msg)) {		err = PTR_ERR(gss_msg);		goto out;	}	spin_lock(&gss_auth->lock);	if (gss_cred->gc_upcall != NULL)		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);	else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {		task->tk_timeout = 0;		gss_cred->gc_upcall = gss_msg;		/* gss_upcall_callback will release the reference to gss_upcall_msg */		atomic_inc(&gss_msg->count);		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);	} else		err = gss_msg->msg.errno;	spin_unlock(&gss_auth->lock);	gss_release_msg(gss_msg);out:	dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid,			cred->cr_uid, err);	return err;}static inline intgss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred){	struct rpc_cred *cred = &gss_cred->gc_base;	struct gss_upcall_msg *gss_msg;	DEFINE_WAIT(wait);	int err = 0;	dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);	gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);	if (IS_ERR(gss_msg)) {		err = PTR_ERR(gss_msg);		goto out;	}	for (;;) {		prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);		spin_lock(&gss_auth->lock);		if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {			spin_unlock(&gss_auth->lock);			break;		}		spin_unlock(&gss_auth->lock);		if (signalled()) {			err = -ERESTARTSYS;			goto out_intr;		}		schedule();	}	if (gss_msg->ctx)		gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));	else		err = gss_msg->msg.errno;out_intr:	finish_wait(&gss_msg->waitqueue, &wait);	gss_release_msg(gss_msg);out:	dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err);	return err;}static ssize_tgss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,		char __user *dst, size_t buflen){	char *data = (char *)msg->data + msg->copied;	ssize_t mlen = msg->len;	ssize_t left;	if (mlen > buflen)		mlen = buflen;	left = copy_to_user(dst, data, mlen);	if (left < 0) {		msg->errno = left;		return left;	}	mlen -= left;	msg->copied += mlen;	msg->errno = 0;	return mlen;}#define MSG_BUF_MAXSIZE 1024static ssize_tgss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen){	const void *p, *end;	void *buf;	struct rpc_clnt *clnt;	struct gss_auth *gss_auth;	struct rpc_cred *cred;	struct gss_upcall_msg *gss_msg;	struct gss_cl_ctx *ctx;	uid_t uid;	int err = -EFBIG;	if (mlen > MSG_BUF_MAXSIZE)		goto out;	err = -ENOMEM;	buf = kmalloc(mlen, GFP_KERNEL);	if (!buf)		goto out;	clnt = RPC_I(filp->f_dentry->d_inode)->private;	err = -EFAULT;	if (copy_from_user(buf, src, mlen))		goto err;	end = (const void *)((char *)buf + mlen);	p = simple_get_bytes(buf, end, &uid, sizeof(uid));	if (IS_ERR(p)) {		err = PTR_ERR(p);		goto err;	}	err = -ENOMEM;	ctx = gss_alloc_context();	if (ctx == NULL)		goto err;	err = 0;	gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);	p = gss_fill_context(p, end, ctx, gss_auth->mech);	if (IS_ERR(p)) {		err = PTR_ERR(p);		if (err != -EACCES)			goto err_put_ctx;	}	spin_lock(&gss_auth->lock);	gss_msg = __gss_find_upcall(gss_auth, uid);	if (gss_msg) {		if (err == 0 && gss_msg->ctx == NULL)			gss_msg->ctx = gss_get_ctx(ctx);		gss_msg->msg.errno = err;		__gss_unhash_msg(gss_msg);		spin_unlock(&gss_auth->lock);		gss_release_msg(gss_msg);	} else {		struct auth_cred acred = { .uid = uid };		spin_unlock(&gss_auth->lock);		cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0);		if (IS_ERR(cred)) {			err = PTR_ERR(cred);			goto err_put_ctx;		}		gss_cred_set_ctx(cred, gss_get_ctx(ctx));	}	gss_put_ctx(ctx);	kfree(buf);	dprintk("RPC:      gss_pipe_downcall returning length %Zu\n", mlen);	return mlen;err_put_ctx:	gss_put_ctx(ctx);err:	kfree(buf);out:	dprintk("RPC:      gss_pipe_downcall returning %d\n", err);	return err;}static voidgss_pipe_release(struct inode *inode){	struct rpc_inode *rpci = RPC_I(inode);	struct rpc_clnt *clnt;	struct rpc_auth *auth;	struct gss_auth *gss_auth;	clnt = rpci->private;	auth = clnt->cl_auth;	gss_auth = container_of(auth, struct gss_auth, rpc_auth);	spin_lock(&gss_auth->lock);	while (!list_empty(&gss_auth->upcalls)) {		struct gss_upcall_msg *gss_msg;		gss_msg = list_entry(gss_auth->upcalls.next,				struct gss_upcall_msg, list);		gss_msg->msg.errno = -EPIPE;		atomic_inc(&gss_msg->count);		__gss_unhash_msg(gss_msg);		spin_unlock(&gss_auth->lock);		gss_release_msg(gss_msg);		spin_lock(&gss_auth->lock);	}	spin_unlock(&gss_auth->lock);}static voidgss_pipe_destroy_msg(struct rpc_pipe_msg *msg){	struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);	static unsigned long ratelimit;	if (msg->errno < 0) {		dprintk("RPC:      gss_pipe_destroy_msg releasing msg %p\n",				gss_msg);		atomic_inc(&gss_msg->count);		gss_unhash_msg(gss_msg);		if (msg->errno == -ETIMEDOUT) {			unsigned long now = jiffies;			if (time_after(now, ratelimit)) {				printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"						    "Please check user daemon is running!\n");				ratelimit = now + 15*HZ;			}		}		gss_release_msg(gss_msg);	}}/*  * NOTE: we have the opportunity to use different  * parameters based on the input flavor (which must be a pseudoflavor) */static struct rpc_auth *gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor){	struct gss_auth *gss_auth;	struct rpc_auth * auth;	int err = -ENOMEM; /* XXX? */	dprintk("RPC:      creating GSS authenticator for client %p\n",clnt);	if (!try_module_get(THIS_MODULE))		return ERR_PTR(err);	if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))		goto out_dec;	gss_auth->client = clnt;	err = -EINVAL;	gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);	if (!gss_auth->mech) {		printk(KERN_WARNING "%s: Pseudoflavor %d not found!",				__FUNCTION__, flavor);		goto err_free;	}	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);	if (gss_auth->service == 0)		goto err_put_mech;	INIT_LIST_HEAD(&gss_auth->upcalls);	spin_lock_init(&gss_auth->lock);	auth = &gss_auth->rpc_auth;	auth->au_cslack = GSS_CRED_SLACK >> 2;	auth->au_rslack = GSS_VERF_SLACK >> 2;	auth->au_ops = &authgss_ops;	auth->au_flavor = flavor;	atomic_set(&auth->au_count, 1);	err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);	if (err)		goto err_put_mech;	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",			clnt->cl_pathname,			gss_auth->mech->gm_name);	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);	if (IS_ERR(gss_auth->dentry)) {		err = PTR_ERR(gss_auth->dentry);		goto err_put_mech;	}	return auth;err_put_mech:	gss_mech_put(gss_auth->mech);err_free:	kfree(gss_auth);out_dec:	module_put(THIS_MODULE);	return ERR_PTR(err);}static voidgss_destroy(struct rpc_auth *auth){	struct gss_auth *gss_auth;	dprintk("RPC:      destroying GSS authenticator %p flavor %d\n",		auth, auth->au_flavor);	gss_auth = container_of(auth, struct gss_auth, rpc_auth);	rpc_unlink(gss_auth->path);	gss_mech_put(gss_auth->mech);	rpcauth_free_credcache(auth);	kfree(gss_auth);	module_put(THIS_MODULE);}/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure * to create a new cred or context, so they check that things have been * allocated before freeing them. */static voidgss_destroy_ctx(struct gss_cl_ctx *ctx){	dprintk("RPC:      gss_destroy_ctx\n");	if (ctx->gc_gss_ctx)		gss_delete_sec_context(&ctx->gc_gss_ctx);	kfree(ctx->gc_wire_ctx.data);	kfree(ctx);}static voidgss_destroy_cred(struct rpc_cred *rc){	struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);	dprintk("RPC:      gss_destroy_cred \n");	if (cred->gc_ctx)		gss_put_ctx(cred->gc_ctx);	kfree(cred);}/* * Lookup RPCSEC_GSS cred for the current process */static struct rpc_cred *gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags){	return rpcauth_lookup_credcache(auth, acred, taskflags);}static struct rpc_cred *gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags){	struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);	struct gss_cred	*cred = NULL;	int err = -ENOMEM;	dprintk("RPC:      gss_create_cred for uid %d, flavor %d\n",		acred->uid, auth->au_flavor);	if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))		goto out_err;	memset(cred, 0, sizeof(*cred));	atomic_set(&cred->gc_count, 1);	cred->gc_uid = acred->uid;	/*	 * Note: in order to force a call to call_refresh(), we deliberately	 * fail to flag the credential as RPCAUTH_CRED_UPTODATE.	 */	cred->gc_flags = 0;	cred->gc_base.cr_ops = &gss_credops;	cred->gc_service = gss_auth->service;	do {		err = gss_create_upcall(gss_auth, cred);	} while (err == -EAGAIN);	if (err < 0)		goto out_err;	return &cred->gc_base;out_err:	dprintk("RPC:      gss_create_cred failed with error %d\n", err);	if (cred) gss_destroy_cred(&cred->gc_base);	return ERR_PTR(err);}static intgss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags){	struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);	/* Don't match with creds that have expired. */	if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))		return 0;	return (rc->cr_uid == acred->uid);}/** Marshal credentials.* Maybe we should keep a cached credential for performance reasons.*/static u32 *gss_marshal(struct rpc_task *task, u32 *p){	struct rpc_cred *cred = task->tk_msg.rpc_cred;	struct gss_cred	*gss_cred = container_of(cred, struct gss_cred,						 gc_base);	struct gss_cl_ctx	*ctx = gss_cred_get_ctx(cred);	u32		*cred_len;	struct rpc_rqst *req = task->tk_rqstp;	u32             maj_stat = 0;	struct xdr_netobj mic;	struct kvec	iov;	struct xdr_buf	verf_buf;	dprintk("RPC: %4u gss_marshal\n", task->tk_pid);	*p++ = htonl(RPC_AUTH_GSS);	cred_len = p++;	spin_lock(&ctx->gc_seq_lock);	req->rq_seqno = ctx->gc_seq++;	spin_unlock(&ctx->gc_seq_lock);	*p++ = htonl((u32) RPC_GSS_VERSION);	*p++ = htonl((u32) ctx->gc_proc);	*p++ = htonl((u32) req->rq_seqno);	*p++ = htonl((u32) gss_cred->gc_service);	p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);	*cred_len = htonl((p - (cred_len + 1)) << 2);	/* We compute the checksum for the verifier over the xdr-encoded bytes	 * starting with the xid and ending at the end of the credential: */	iov.iov_base = xprt_skip_transport_header(task->tk_xprt,					req->rq_snd_buf.head[0].iov_base);	iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;	xdr_buf_from_iov(&iov, &verf_buf);	/* set verifier flavor*/	*p++ = htonl(RPC_AUTH_GSS);	mic.data = (u8 *)(p + 1);	maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);	if (maj_stat == GSS_S_CONTEXT_EXPIRED) {

⌨️ 快捷键说明

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