diff options
Diffstat (limited to 'net/sunrpc/auth_generic.c')
-rw-r--r-- | net/sunrpc/auth_generic.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index b6badafc6494..f6d84be49050 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -89,6 +89,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
89 | gcred->acred.uid = acred->uid; | 89 | gcred->acred.uid = acred->uid; |
90 | gcred->acred.gid = acred->gid; | 90 | gcred->acred.gid = acred->gid; |
91 | gcred->acred.group_info = acred->group_info; | 91 | gcred->acred.group_info = acred->group_info; |
92 | gcred->acred.ac_flags = 0; | ||
92 | if (gcred->acred.group_info != NULL) | 93 | if (gcred->acred.group_info != NULL) |
93 | get_group_info(gcred->acred.group_info); | 94 | get_group_info(gcred->acred.group_info); |
94 | gcred->acred.machine_cred = acred->machine_cred; | 95 | gcred->acred.machine_cred = acred->machine_cred; |
@@ -182,11 +183,78 @@ void rpc_destroy_generic_auth(void) | |||
182 | rpcauth_destroy_credcache(&generic_auth); | 183 | rpcauth_destroy_credcache(&generic_auth); |
183 | } | 184 | } |
184 | 185 | ||
186 | /* | ||
187 | * Test the the current time (now) against the underlying credential key expiry | ||
188 | * minus a timeout and setup notification. | ||
189 | * | ||
190 | * The normal case: | ||
191 | * If 'now' is before the key expiry minus RPC_KEY_EXPIRE_TIMEO, set | ||
192 | * the RPC_CRED_NOTIFY_TIMEOUT flag to setup the underlying credential | ||
193 | * rpc_credops crmatch routine to notify this generic cred when it's key | ||
194 | * expiration is within RPC_KEY_EXPIRE_TIMEO, and return 0. | ||
195 | * | ||
196 | * The error case: | ||
197 | * If the underlying cred lookup fails, return -EACCES. | ||
198 | * | ||
199 | * The 'almost' error case: | ||
200 | * If 'now' is within key expiry minus RPC_KEY_EXPIRE_TIMEO, but not within | ||
201 | * key expiry minus RPC_KEY_EXPIRE_FAIL, set the RPC_CRED_EXPIRE_SOON bit | ||
202 | * on the acred ac_flags and return 0. | ||
203 | */ | ||
204 | static int | ||
205 | generic_key_timeout(struct rpc_auth *auth, struct rpc_cred *cred) | ||
206 | { | ||
207 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | ||
208 | gc_base)->acred; | ||
209 | struct rpc_cred *tcred; | ||
210 | int ret = 0; | ||
211 | |||
212 | |||
213 | /* Fast track for non crkey_timeout (no key) underlying credentials */ | ||
214 | if (test_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags)) | ||
215 | return 0; | ||
216 | |||
217 | /* Fast track for the normal case */ | ||
218 | if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags)) | ||
219 | return 0; | ||
220 | |||
221 | /* lookup_cred either returns a valid referenced rpc_cred, or PTR_ERR */ | ||
222 | tcred = auth->au_ops->lookup_cred(auth, acred, 0); | ||
223 | if (IS_ERR(tcred)) | ||
224 | return -EACCES; | ||
225 | |||
226 | if (!tcred->cr_ops->crkey_timeout) { | ||
227 | set_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags); | ||
228 | ret = 0; | ||
229 | goto out_put; | ||
230 | } | ||
231 | |||
232 | /* Test for the almost error case */ | ||
233 | ret = tcred->cr_ops->crkey_timeout(tcred); | ||
234 | if (ret != 0) { | ||
235 | set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
236 | ret = 0; | ||
237 | } else { | ||
238 | /* In case underlying cred key has been reset */ | ||
239 | if (test_and_clear_bit(RPC_CRED_KEY_EXPIRE_SOON, | ||
240 | &acred->ac_flags)) | ||
241 | dprintk("RPC: UID %d Credential key reset\n", | ||
242 | tcred->cr_uid); | ||
243 | /* set up fasttrack for the normal case */ | ||
244 | set_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags); | ||
245 | } | ||
246 | |||
247 | out_put: | ||
248 | put_rpccred(tcred); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
185 | static const struct rpc_authops generic_auth_ops = { | 252 | static const struct rpc_authops generic_auth_ops = { |
186 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
187 | .au_name = "Generic", | 254 | .au_name = "Generic", |
188 | .lookup_cred = generic_lookup_cred, | 255 | .lookup_cred = generic_lookup_cred, |
189 | .crcreate = generic_create_cred, | 256 | .crcreate = generic_create_cred, |
257 | .key_timeout = generic_key_timeout, | ||
190 | }; | 258 | }; |
191 | 259 | ||
192 | static struct rpc_auth generic_auth = { | 260 | static struct rpc_auth generic_auth = { |
@@ -194,9 +262,23 @@ static struct rpc_auth generic_auth = { | |||
194 | .au_count = ATOMIC_INIT(0), | 262 | .au_count = ATOMIC_INIT(0), |
195 | }; | 263 | }; |
196 | 264 | ||
265 | static bool generic_key_to_expire(struct rpc_cred *cred) | ||
266 | { | ||
267 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | ||
268 | gc_base)->acred; | ||
269 | bool ret; | ||
270 | |||
271 | get_rpccred(cred); | ||
272 | ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
273 | put_rpccred(cred); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
197 | static const struct rpc_credops generic_credops = { | 278 | static const struct rpc_credops generic_credops = { |
198 | .cr_name = "Generic cred", | 279 | .cr_name = "Generic cred", |
199 | .crdestroy = generic_destroy_cred, | 280 | .crdestroy = generic_destroy_cred, |
200 | .crbind = generic_bind_cred, | 281 | .crbind = generic_bind_cred, |
201 | .crmatch = generic_match, | 282 | .crmatch = generic_match, |
283 | .crkey_to_expire = generic_key_to_expire, | ||
202 | }; | 284 | }; |