diff options
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 126 |
1 files changed, 90 insertions, 36 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index b6e440baccc3..afb292cd797d 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -183,8 +183,9 @@ gss_cred_get_ctx(struct rpc_cred *cred) | |||
183 | struct gss_cl_ctx *ctx = NULL; | 183 | struct gss_cl_ctx *ctx = NULL; |
184 | 184 | ||
185 | rcu_read_lock(); | 185 | rcu_read_lock(); |
186 | if (gss_cred->gc_ctx) | 186 | ctx = rcu_dereference(gss_cred->gc_ctx); |
187 | ctx = gss_get_ctx(gss_cred->gc_ctx); | 187 | if (ctx) |
188 | gss_get_ctx(ctx); | ||
188 | rcu_read_unlock(); | 189 | rcu_read_unlock(); |
189 | return ctx; | 190 | return ctx; |
190 | } | 191 | } |
@@ -262,9 +263,22 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
262 | p = ERR_PTR(ret); | 263 | p = ERR_PTR(ret); |
263 | goto err; | 264 | goto err; |
264 | } | 265 | } |
265 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u\n", | 266 | |
266 | __func__, ctx->gc_expiry, now, timeout); | 267 | /* is there any trailing data? */ |
267 | return q; | 268 | if (q == end) { |
269 | p = q; | ||
270 | goto done; | ||
271 | } | ||
272 | |||
273 | /* pull in acceptor name (if there is one) */ | ||
274 | p = simple_get_netobj(q, end, &ctx->gc_acceptor); | ||
275 | if (IS_ERR(p)) | ||
276 | goto err; | ||
277 | done: | ||
278 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u acceptor %.*s\n", | ||
279 | __func__, ctx->gc_expiry, now, timeout, ctx->gc_acceptor.len, | ||
280 | ctx->gc_acceptor.data); | ||
281 | return p; | ||
268 | err: | 282 | err: |
269 | dprintk("RPC: %s returns error %ld\n", __func__, -PTR_ERR(p)); | 283 | dprintk("RPC: %s returns error %ld\n", __func__, -PTR_ERR(p)); |
270 | return p; | 284 | return p; |
@@ -1194,13 +1208,13 @@ gss_destroying_context(struct rpc_cred *cred) | |||
1194 | { | 1208 | { |
1195 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1209 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1196 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 1210 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
1211 | struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); | ||
1197 | struct rpc_task *task; | 1212 | struct rpc_task *task; |
1198 | 1213 | ||
1199 | if (gss_cred->gc_ctx == NULL || | 1214 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) |
1200 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | ||
1201 | return 0; | 1215 | return 0; |
1202 | 1216 | ||
1203 | gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY; | 1217 | ctx->gc_proc = RPC_GSS_PROC_DESTROY; |
1204 | cred->cr_ops = &gss_nullops; | 1218 | cred->cr_ops = &gss_nullops; |
1205 | 1219 | ||
1206 | /* Take a reference to ensure the cred will be destroyed either | 1220 | /* Take a reference to ensure the cred will be destroyed either |
@@ -1225,6 +1239,7 @@ gss_do_free_ctx(struct gss_cl_ctx *ctx) | |||
1225 | 1239 | ||
1226 | gss_delete_sec_context(&ctx->gc_gss_ctx); | 1240 | gss_delete_sec_context(&ctx->gc_gss_ctx); |
1227 | kfree(ctx->gc_wire_ctx.data); | 1241 | kfree(ctx->gc_wire_ctx.data); |
1242 | kfree(ctx->gc_acceptor.data); | ||
1228 | kfree(ctx); | 1243 | kfree(ctx); |
1229 | } | 1244 | } |
1230 | 1245 | ||
@@ -1260,7 +1275,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) | |||
1260 | { | 1275 | { |
1261 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1276 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1262 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 1277 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
1263 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; | 1278 | struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); |
1264 | 1279 | ||
1265 | RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); | 1280 | RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); |
1266 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | 1281 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
@@ -1332,6 +1347,36 @@ gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) | |||
1332 | return err; | 1347 | return err; |
1333 | } | 1348 | } |
1334 | 1349 | ||
1350 | static char * | ||
1351 | gss_stringify_acceptor(struct rpc_cred *cred) | ||
1352 | { | ||
1353 | char *string = NULL; | ||
1354 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | ||
1355 | struct gss_cl_ctx *ctx; | ||
1356 | struct xdr_netobj *acceptor; | ||
1357 | |||
1358 | rcu_read_lock(); | ||
1359 | ctx = rcu_dereference(gss_cred->gc_ctx); | ||
1360 | if (!ctx) | ||
1361 | goto out; | ||
1362 | |||
1363 | acceptor = &ctx->gc_acceptor; | ||
1364 | |||
1365 | /* no point if there's no string */ | ||
1366 | if (!acceptor->len) | ||
1367 | goto out; | ||
1368 | |||
1369 | string = kmalloc(acceptor->len + 1, GFP_KERNEL); | ||
1370 | if (!string) | ||
1371 | goto out; | ||
1372 | |||
1373 | memcpy(string, acceptor->data, acceptor->len); | ||
1374 | string[acceptor->len] = '\0'; | ||
1375 | out: | ||
1376 | rcu_read_unlock(); | ||
1377 | return string; | ||
1378 | } | ||
1379 | |||
1335 | /* | 1380 | /* |
1336 | * Returns -EACCES if GSS context is NULL or will expire within the | 1381 | * Returns -EACCES if GSS context is NULL or will expire within the |
1337 | * timeout (miliseconds) | 1382 | * timeout (miliseconds) |
@@ -1340,15 +1385,16 @@ static int | |||
1340 | gss_key_timeout(struct rpc_cred *rc) | 1385 | gss_key_timeout(struct rpc_cred *rc) |
1341 | { | 1386 | { |
1342 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 1387 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
1388 | struct gss_cl_ctx *ctx; | ||
1343 | unsigned long now = jiffies; | 1389 | unsigned long now = jiffies; |
1344 | unsigned long expire; | 1390 | unsigned long expire; |
1345 | 1391 | ||
1346 | if (gss_cred->gc_ctx == NULL) | 1392 | rcu_read_lock(); |
1347 | return -EACCES; | 1393 | ctx = rcu_dereference(gss_cred->gc_ctx); |
1348 | 1394 | if (ctx) | |
1349 | expire = gss_cred->gc_ctx->gc_expiry - (gss_key_expire_timeo * HZ); | 1395 | expire = ctx->gc_expiry - (gss_key_expire_timeo * HZ); |
1350 | 1396 | rcu_read_unlock(); | |
1351 | if (time_after(now, expire)) | 1397 | if (!ctx || time_after(now, expire)) |
1352 | return -EACCES; | 1398 | return -EACCES; |
1353 | return 0; | 1399 | return 0; |
1354 | } | 1400 | } |
@@ -1357,13 +1403,19 @@ static int | |||
1357 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | 1403 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
1358 | { | 1404 | { |
1359 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 1405 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
1406 | struct gss_cl_ctx *ctx; | ||
1360 | int ret; | 1407 | int ret; |
1361 | 1408 | ||
1362 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) | 1409 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
1363 | goto out; | 1410 | goto out; |
1364 | /* Don't match with creds that have expired. */ | 1411 | /* Don't match with creds that have expired. */ |
1365 | if (time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 1412 | rcu_read_lock(); |
1413 | ctx = rcu_dereference(gss_cred->gc_ctx); | ||
1414 | if (!ctx || time_after(jiffies, ctx->gc_expiry)) { | ||
1415 | rcu_read_unlock(); | ||
1366 | return 0; | 1416 | return 0; |
1417 | } | ||
1418 | rcu_read_unlock(); | ||
1367 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) | 1419 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) |
1368 | return 0; | 1420 | return 0; |
1369 | out: | 1421 | out: |
@@ -1909,29 +1961,31 @@ static const struct rpc_authops authgss_ops = { | |||
1909 | }; | 1961 | }; |
1910 | 1962 | ||
1911 | static const struct rpc_credops gss_credops = { | 1963 | static const struct rpc_credops gss_credops = { |
1912 | .cr_name = "AUTH_GSS", | 1964 | .cr_name = "AUTH_GSS", |
1913 | .crdestroy = gss_destroy_cred, | 1965 | .crdestroy = gss_destroy_cred, |
1914 | .cr_init = gss_cred_init, | 1966 | .cr_init = gss_cred_init, |
1915 | .crbind = rpcauth_generic_bind_cred, | 1967 | .crbind = rpcauth_generic_bind_cred, |
1916 | .crmatch = gss_match, | 1968 | .crmatch = gss_match, |
1917 | .crmarshal = gss_marshal, | 1969 | .crmarshal = gss_marshal, |
1918 | .crrefresh = gss_refresh, | 1970 | .crrefresh = gss_refresh, |
1919 | .crvalidate = gss_validate, | 1971 | .crvalidate = gss_validate, |
1920 | .crwrap_req = gss_wrap_req, | 1972 | .crwrap_req = gss_wrap_req, |
1921 | .crunwrap_resp = gss_unwrap_resp, | 1973 | .crunwrap_resp = gss_unwrap_resp, |
1922 | .crkey_timeout = gss_key_timeout, | 1974 | .crkey_timeout = gss_key_timeout, |
1975 | .crstringify_acceptor = gss_stringify_acceptor, | ||
1923 | }; | 1976 | }; |
1924 | 1977 | ||
1925 | static const struct rpc_credops gss_nullops = { | 1978 | static const struct rpc_credops gss_nullops = { |
1926 | .cr_name = "AUTH_GSS", | 1979 | .cr_name = "AUTH_GSS", |
1927 | .crdestroy = gss_destroy_nullcred, | 1980 | .crdestroy = gss_destroy_nullcred, |
1928 | .crbind = rpcauth_generic_bind_cred, | 1981 | .crbind = rpcauth_generic_bind_cred, |
1929 | .crmatch = gss_match, | 1982 | .crmatch = gss_match, |
1930 | .crmarshal = gss_marshal, | 1983 | .crmarshal = gss_marshal, |
1931 | .crrefresh = gss_refresh_null, | 1984 | .crrefresh = gss_refresh_null, |
1932 | .crvalidate = gss_validate, | 1985 | .crvalidate = gss_validate, |
1933 | .crwrap_req = gss_wrap_req, | 1986 | .crwrap_req = gss_wrap_req, |
1934 | .crunwrap_resp = gss_unwrap_resp, | 1987 | .crunwrap_resp = gss_unwrap_resp, |
1988 | .crstringify_acceptor = gss_stringify_acceptor, | ||
1935 | }; | 1989 | }; |
1936 | 1990 | ||
1937 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { | 1991 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { |