/* * Return the machine_cred pointer to be used whenever * the a generic machine credential is needed.
*/ conststruct cred *rpc_machine_cred(void)
{ return &machine_cred;
}
EXPORT_SYMBOL_GPL(rpc_machine_cred);
/** * rpcauth_get_pseudoflavor - check if security flavor is supported * @flavor: a security flavor * @info: a GSS mech OID, quality of protection, and service value * * Verifies that an appropriate kernel module is available or already loaded. * Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is * not supported locally.
*/
rpc_authflavor_t
rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
{ conststruct rpc_authops *ops = rpcauth_get_authops(flavor);
rpc_authflavor_t pseudoflavor;
if (!ops) return RPC_AUTH_MAXFLAVOR;
pseudoflavor = flavor; if (ops->info2flavor != NULL)
pseudoflavor = ops->info2flavor(info);
/** * rpcauth_get_gssinfo - find GSS tuple matching a GSS pseudoflavor * @pseudoflavor: GSS pseudoflavor to match * @info: rpcsec_gss_info structure to fill in * * Returns zero and fills in "info" if pseudoflavor matches a * supported mechanism.
*/ int
rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
{
rpc_authflavor_t flavor = pseudoflavor_to_flavor(pseudoflavor); conststruct rpc_authops *ops; int result;
ops = rpcauth_get_authops(flavor); if (ops == NULL) return -ENOENT;
result = -ENOENT; if (ops->flavor2info != NULL)
result = ops->flavor2info(pseudoflavor, info);
void
rpcauth_release(struct rpc_auth *auth)
{ if (!refcount_dec_and_test(&auth->au_count)) return;
auth->au_ops->destroy(auth);
}
static DEFINE_SPINLOCK(rpc_credcache_lock);
/* * On success, the caller is responsible for freeing the reference * held by the hashtable
*/ staticbool
rpcauth_unhash_cred_locked(struct rpc_cred *cred)
{ if (!test_and_clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags)) returnfalse;
hlist_del_rcu(&cred->cr_hash); returntrue;
}
/* * Clear the RPC credential cache, and delete those credentials * that are not referenced.
*/ void
rpcauth_clear_credcache(struct rpc_cred_cache *cache)
{
LIST_HEAD(free); struct hlist_head *head; struct rpc_cred *cred; unsignedint hashsize = 1U << cache->hashbits; int i;
spin_lock(&rpc_credcache_lock);
spin_lock(&cache->lock); for (i = 0; i < hashsize; i++) {
head = &cache->hashtable[i]; while (!hlist_empty(head)) {
cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
rpcauth_unhash_cred_locked(cred); /* Note: We now hold a reference to cred */
rpcauth_lru_remove_locked(cred);
list_add_tail(&cred->cr_lru, &free);
}
}
spin_unlock(&cache->lock);
spin_unlock(&rpc_credcache_lock);
rpcauth_destroy_credlist(&free);
}
if (nr_to_scan-- == 0) break; if (refcount_read(&cred->cr_count) > 1) {
rpcauth_lru_remove_locked(cred); continue;
} /* * Enforce a 60 second garbage collection moratorium * Note that the cred_unused list must be time-ordered.
*/ if (time_in_range(cred->cr_expire, expired, jiffies)) continue; if (!rpcauth_unhash_cred(cred)) continue;
if (flags & RPC_TASK_ASYNC)
lookupflags |= RPCAUTH_LOOKUP_NEW | RPCAUTH_LOOKUP_ASYNC; if (task->tk_op_cred) /* Task must use exactly this rpc_cred */ new = get_rpccred(task->tk_op_cred); elseif (cred != NULL && cred != &machine_cred) new = auth->au_ops->lookup_cred(auth, &acred, lookupflags); elseif (cred == &machine_cred) new = rpcauth_bind_machine_cred(task, lookupflags);
/* If machine cred couldn't be bound, try a root cred */ if (new)
; elseif (cred == &machine_cred) new = rpcauth_bind_root_cred(task, lookupflags); elseif (flags & RPC_TASK_NULLCREDS) new = authnull_ops.lookup_cred(NULL, NULL, 0); else new = rpcauth_bind_new_cred(task, lookupflags); if (IS_ERR(new)) return PTR_ERR(new);
put_rpccred(req->rq_cred);
req->rq_cred = new; return 0;
}
void
put_rpccred(struct rpc_cred *cred)
{ if (cred == NULL) return;
rcu_read_lock(); if (refcount_dec_and_test(&cred->cr_count)) goto destroy; if (refcount_read(&cred->cr_count) != 1 ||
!test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags)) goto out; if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
cred->cr_expire = jiffies;
rpcauth_lru_add(cred); /* Race breaker */ if (unlikely(!test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags)))
rpcauth_lru_remove(cred);
} elseif (rpcauth_unhash_cred(cred)) {
rpcauth_lru_remove(cred); if (refcount_dec_and_test(&cred->cr_count)) goto destroy;
}
out:
rcu_read_unlock(); return;
destroy:
rcu_read_unlock();
cred->cr_ops->crdestroy(cred);
}
EXPORT_SYMBOL_GPL(put_rpccred);
/** * rpcauth_marshcred - Append RPC credential to end of @xdr * @task: controlling RPC task * @xdr: xdr_stream containing initial portion of RPC Call header * * On success, an appropriate verifier is added to @xdr, @xdr is * updated to point past the verifier, and zero is returned. * Otherwise, @xdr is in an undefined state and a negative errno * is returned.
*/ int rpcauth_marshcred(struct rpc_task *task, struct xdr_stream *xdr)
{ conststruct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
return ops->crmarshal(task, xdr);
}
/** * rpcauth_wrap_req_encode - XDR encode the RPC procedure * @task: controlling RPC task * @xdr: stream where on-the-wire bytes are to be marshalled * * On success, @xdr contains the encoded and wrapped message. * Otherwise, @xdr is in an undefined state.
*/ int rpcauth_wrap_req_encode(struct rpc_task *task, struct xdr_stream *xdr)
{
kxdreproc_t encode = task->tk_msg.rpc_proc->p_encode;
/** * rpcauth_wrap_req - XDR encode and wrap the RPC procedure * @task: controlling RPC task * @xdr: stream where on-the-wire bytes are to be marshalled * * On success, @xdr contains the encoded and wrapped message, * and zero is returned. Otherwise, @xdr is in an undefined * state and a negative errno is returned.
*/ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
{ conststruct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
return ops->crwrap_req(task, xdr);
}
/** * rpcauth_checkverf - Validate verifier in RPC Reply header * @task: controlling RPC task * @xdr: xdr_stream containing RPC Reply header * * Return values: * %0: Verifier is valid. @xdr now points past the verifier. * %-EIO: Verifier is corrupted or message ended early. * %-EACCES: Verifier is intact but not valid. * %-EPROTONOSUPPORT: Server does not support the requested auth type. * * When a negative errno is returned, @xdr is left in an undefined * state.
*/ int
rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
{ conststruct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
return ops->crvalidate(task, xdr);
}
/** * rpcauth_unwrap_resp_decode - Invoke XDR decode function * @task: controlling RPC task * @xdr: stream where the Reply message resides * * Returns zero on success; otherwise a negative errno is returned.
*/ int
rpcauth_unwrap_resp_decode(struct rpc_task *task, struct xdr_stream *xdr)
{
kxdrdproc_t decode = task->tk_msg.rpc_proc->p_decode;
/** * rpcauth_unwrap_resp - Invoke unwrap and decode function for the cred * @task: controlling RPC task * @xdr: stream where the Reply message resides * * Returns zero on success; otherwise a negative errno is returned.
*/ int
rpcauth_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr)
{ conststruct rpc_credops *ops = task->tk_rqstp->rq_cred->cr_ops;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.