@@ -57,6 +57,9 @@ static const struct rpc_authops authgss_ops;
57
57
static const struct rpc_credops gss_credops ;
58
58
static const struct rpc_credops gss_nullops ;
59
59
60
+ #define GSS_RETRY_EXPIRED 5
61
+ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED ;
62
+
60
63
#ifdef RPC_DEBUG
61
64
# define RPCDBG_FACILITY RPCDBG_AUTH
62
65
#endif
@@ -349,6 +352,24 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
349
352
spin_unlock (& inode -> i_lock );
350
353
}
351
354
355
+ static void
356
+ gss_handle_downcall_result (struct gss_cred * gss_cred , struct gss_upcall_msg * gss_msg )
357
+ {
358
+ switch (gss_msg -> msg .errno ) {
359
+ case 0 :
360
+ if (gss_msg -> ctx == NULL )
361
+ break ;
362
+ clear_bit (RPCAUTH_CRED_NEGATIVE , & gss_cred -> gc_base .cr_flags );
363
+ gss_cred_set_ctx (& gss_cred -> gc_base , gss_msg -> ctx );
364
+ break ;
365
+ case - EKEYEXPIRED :
366
+ set_bit (RPCAUTH_CRED_NEGATIVE , & gss_cred -> gc_base .cr_flags );
367
+ }
368
+ gss_cred -> gc_upcall_timestamp = jiffies ;
369
+ gss_cred -> gc_upcall = NULL ;
370
+ rpc_wake_up_status (& gss_msg -> rpc_waitqueue , gss_msg -> msg .errno );
371
+ }
372
+
352
373
static void
353
374
gss_upcall_callback (struct rpc_task * task )
354
375
{
@@ -358,13 +379,9 @@ gss_upcall_callback(struct rpc_task *task)
358
379
struct inode * inode = & gss_msg -> inode -> vfs_inode ;
359
380
360
381
spin_lock (& inode -> i_lock );
361
- if (gss_msg -> ctx )
362
- gss_cred_set_ctx (task -> tk_msg .rpc_cred , gss_msg -> ctx );
363
- else
364
- task -> tk_status = gss_msg -> msg .errno ;
365
- gss_cred -> gc_upcall = NULL ;
366
- rpc_wake_up_status (& gss_msg -> rpc_waitqueue , gss_msg -> msg .errno );
382
+ gss_handle_downcall_result (gss_cred , gss_msg );
367
383
spin_unlock (& inode -> i_lock );
384
+ task -> tk_status = gss_msg -> msg .errno ;
368
385
gss_release_msg (gss_msg );
369
386
}
370
387
@@ -513,18 +530,16 @@ gss_refresh_upcall(struct rpc_task *task)
513
530
spin_lock (& inode -> i_lock );
514
531
if (gss_cred -> gc_upcall != NULL )
515
532
rpc_sleep_on (& gss_cred -> gc_upcall -> rpc_waitqueue , task , NULL );
516
- else if (gss_msg -> ctx != NULL ) {
517
- gss_cred_set_ctx (task -> tk_msg .rpc_cred , gss_msg -> ctx );
518
- gss_cred -> gc_upcall = NULL ;
519
- rpc_wake_up_status (& gss_msg -> rpc_waitqueue , gss_msg -> msg .errno );
520
- } else if (gss_msg -> msg .errno >= 0 ) {
533
+ else if (gss_msg -> ctx == NULL && gss_msg -> msg .errno >= 0 ) {
521
534
task -> tk_timeout = 0 ;
522
535
gss_cred -> gc_upcall = gss_msg ;
523
536
/* gss_upcall_callback will release the reference to gss_upcall_msg */
524
537
atomic_inc (& gss_msg -> count );
525
538
rpc_sleep_on (& gss_msg -> rpc_waitqueue , task , gss_upcall_callback );
526
- } else
539
+ } else {
540
+ gss_handle_downcall_result (gss_cred , gss_msg );
527
541
err = gss_msg -> msg .errno ;
542
+ }
528
543
spin_unlock (& inode -> i_lock );
529
544
gss_release_msg (gss_msg );
530
545
out :
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task)
1123
1138
return 0 ;
1124
1139
}
1125
1140
1141
+ static int gss_cred_is_negative_entry (struct rpc_cred * cred )
1142
+ {
1143
+ if (test_bit (RPCAUTH_CRED_NEGATIVE , & cred -> cr_flags )) {
1144
+ unsigned long now = jiffies ;
1145
+ unsigned long begin , expire ;
1146
+ struct gss_cred * gss_cred ;
1147
+
1148
+ gss_cred = container_of (cred , struct gss_cred , gc_base );
1149
+ begin = gss_cred -> gc_upcall_timestamp ;
1150
+ expire = begin + gss_expired_cred_retry_delay * HZ ;
1151
+
1152
+ if (time_in_range_open (now , begin , expire ))
1153
+ return 1 ;
1154
+ }
1155
+ return 0 ;
1156
+ }
1157
+
1126
1158
/*
1127
1159
* Refresh credentials. XXX - finish
1128
1160
*/
@@ -1132,6 +1164,9 @@ gss_refresh(struct rpc_task *task)
1132
1164
struct rpc_cred * cred = task -> tk_msg .rpc_cred ;
1133
1165
int ret = 0 ;
1134
1166
1167
+ if (gss_cred_is_negative_entry (cred ))
1168
+ return - EKEYEXPIRED ;
1169
+
1135
1170
if (!test_bit (RPCAUTH_CRED_NEW , & cred -> cr_flags ) &&
1136
1171
!test_bit (RPCAUTH_CRED_UPTODATE , & cred -> cr_flags )) {
1137
1172
ret = gss_renew_cred (task );
@@ -1585,5 +1620,11 @@ static void __exit exit_rpcsec_gss(void)
1585
1620
}
1586
1621
1587
1622
MODULE_LICENSE ("GPL" );
1623
+ module_param_named (expired_cred_retry_delay ,
1624
+ gss_expired_cred_retry_delay ,
1625
+ uint , 0644 );
1626
+ MODULE_PARM_DESC (expired_cred_retry_delay , "Timeout (in seconds) until "
1627
+ "the RPC engine retries an expired credential" );
1628
+
1588
1629
module_init (init_rpcsec_gss )
1589
1630
module_exit (exit_rpcsec_gss )
0 commit comments