|
@@ -57,6 +57,9 @@ static const struct rpc_authops authgss_ops;
|
|
|
static const struct rpc_credops gss_credops;
|
|
|
static const struct rpc_credops gss_nullops;
|
|
|
|
|
|
+#define GSS_RETRY_EXPIRED 5
|
|
|
+static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
|
|
|
+
|
|
|
#ifdef RPC_DEBUG
|
|
|
# define RPCDBG_FACILITY RPCDBG_AUTH
|
|
|
#endif
|
|
@@ -349,6 +352,24 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg)
|
|
|
+{
|
|
|
+ switch (gss_msg->msg.errno) {
|
|
|
+ case 0:
|
|
|
+ if (gss_msg->ctx == NULL)
|
|
|
+ break;
|
|
|
+ clear_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
|
|
|
+ gss_cred_set_ctx(&gss_cred->gc_base, gss_msg->ctx);
|
|
|
+ break;
|
|
|
+ case -EKEYEXPIRED:
|
|
|
+ set_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
|
|
|
+ }
|
|
|
+ gss_cred->gc_upcall_timestamp = jiffies;
|
|
|
+ gss_cred->gc_upcall = NULL;
|
|
|
+ rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
gss_upcall_callback(struct rpc_task *task)
|
|
|
{
|
|
@@ -358,13 +379,9 @@ gss_upcall_callback(struct rpc_task *task)
|
|
|
struct inode *inode = &gss_msg->inode->vfs_inode;
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
- if (gss_msg->ctx)
|
|
|
- gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
|
|
|
- else
|
|
|
- task->tk_status = gss_msg->msg.errno;
|
|
|
- gss_cred->gc_upcall = NULL;
|
|
|
- rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
|
|
|
+ gss_handle_downcall_result(gss_cred, gss_msg);
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
+ task->tk_status = gss_msg->msg.errno;
|
|
|
gss_release_msg(gss_msg);
|
|
|
}
|
|
|
|
|
@@ -513,18 +530,16 @@ gss_refresh_upcall(struct rpc_task *task)
|
|
|
spin_lock(&inode->i_lock);
|
|
|
if (gss_cred->gc_upcall != NULL)
|
|
|
rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
|
|
|
- else if (gss_msg->ctx != NULL) {
|
|
|
- gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
|
|
|
- gss_cred->gc_upcall = NULL;
|
|
|
- rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
|
|
|
- } else if (gss_msg->msg.errno >= 0) {
|
|
|
+ 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);
|
|
|
- } else
|
|
|
+ } else {
|
|
|
+ gss_handle_downcall_result(gss_cred, gss_msg);
|
|
|
err = gss_msg->msg.errno;
|
|
|
+ }
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
gss_release_msg(gss_msg);
|
|
|
out:
|
|
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int gss_cred_is_negative_entry(struct rpc_cred *cred)
|
|
|
+{
|
|
|
+ if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) {
|
|
|
+ unsigned long now = jiffies;
|
|
|
+ unsigned long begin, expire;
|
|
|
+ struct gss_cred *gss_cred;
|
|
|
+
|
|
|
+ gss_cred = container_of(cred, struct gss_cred, gc_base);
|
|
|
+ begin = gss_cred->gc_upcall_timestamp;
|
|
|
+ expire = begin + gss_expired_cred_retry_delay * HZ;
|
|
|
+
|
|
|
+ if (time_in_range_open(now, begin, expire))
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Refresh credentials. XXX - finish
|
|
|
*/
|
|
@@ -1132,6 +1164,9 @@ gss_refresh(struct rpc_task *task)
|
|
|
struct rpc_cred *cred = task->tk_msg.rpc_cred;
|
|
|
int ret = 0;
|
|
|
|
|
|
+ if (gss_cred_is_negative_entry(cred))
|
|
|
+ return -EKEYEXPIRED;
|
|
|
+
|
|
|
if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
|
|
|
!test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
|
|
|
ret = gss_renew_cred(task);
|
|
@@ -1585,5 +1620,11 @@ static void __exit exit_rpcsec_gss(void)
|
|
|
}
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
+module_param_named(expired_cred_retry_delay,
|
|
|
+ gss_expired_cred_retry_delay,
|
|
|
+ uint, 0644);
|
|
|
+MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until "
|
|
|
+ "the RPC engine retries an expired credential");
|
|
|
+
|
|
|
module_init(init_rpcsec_gss)
|
|
|
module_exit(exit_rpcsec_gss)
|