diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6f1b4e2f5e81..621c07f322c4 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -114,28 +114,14 @@ static void | |||
114 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | 114 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) |
115 | { | 115 | { |
116 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 116 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
117 | struct gss_cl_ctx *old; | ||
118 | 117 | ||
119 | old = gss_cred->gc_ctx; | 118 | if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) |
119 | return; | ||
120 | gss_get_ctx(ctx); | 120 | gss_get_ctx(ctx); |
121 | rcu_assign_pointer(gss_cred->gc_ctx, ctx); | 121 | rcu_assign_pointer(gss_cred->gc_ctx, ctx); |
122 | set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 122 | set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
123 | smp_mb__before_clear_bit(); | ||
123 | clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); | 124 | clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); |
124 | if (old) | ||
125 | gss_put_ctx(old); | ||
126 | } | ||
127 | |||
128 | static int | ||
129 | gss_cred_is_uptodate_ctx(struct rpc_cred *cred) | ||
130 | { | ||
131 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | ||
132 | int res = 0; | ||
133 | |||
134 | rcu_read_lock(); | ||
135 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx) | ||
136 | res = 1; | ||
137 | rcu_read_unlock(); | ||
138 | return res; | ||
139 | } | 125 | } |
140 | 126 | ||
141 | static const void * | 127 | static const void * |
@@ -857,15 +843,12 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | |||
857 | { | 843 | { |
858 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 844 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
859 | 845 | ||
860 | /* | 846 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
861 | * If the searchflags have set RPCAUTH_LOOKUP_NEW, then | ||
862 | * we don't really care if the credential has expired or not, | ||
863 | * since the caller should be prepared to reinitialise it. | ||
864 | */ | ||
865 | if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) | ||
866 | goto out; | 847 | goto out; |
867 | /* Don't match with creds that have expired. */ | 848 | /* Don't match with creds that have expired. */ |
868 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 849 | if (time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) |
850 | return 0; | ||
851 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) | ||
869 | return 0; | 852 | return 0; |
870 | out: | 853 | out: |
871 | if (acred->machine_cred != gss_cred->gc_machine_cred) | 854 | if (acred->machine_cred != gss_cred->gc_machine_cred) |
@@ -933,16 +916,48 @@ out_put_ctx: | |||
933 | return NULL; | 916 | return NULL; |
934 | } | 917 | } |
935 | 918 | ||
919 | static int gss_renew_cred(struct rpc_task *task) | ||
920 | { | ||
921 | struct rpc_cred *oldcred = task->tk_msg.rpc_cred; | ||
922 | struct gss_cred *gss_cred = container_of(oldcred, | ||
923 | struct gss_cred, | ||
924 | gc_base); | ||
925 | struct rpc_auth *auth = oldcred->cr_auth; | ||
926 | struct auth_cred acred = { | ||
927 | .uid = oldcred->cr_uid, | ||
928 | .machine_cred = gss_cred->gc_machine_cred, | ||
929 | }; | ||
930 | struct rpc_cred *new; | ||
931 | |||
932 | new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW); | ||
933 | if (IS_ERR(new)) | ||
934 | return PTR_ERR(new); | ||
935 | task->tk_msg.rpc_cred = new; | ||
936 | put_rpccred(oldcred); | ||
937 | return 0; | ||
938 | } | ||
939 | |||
936 | /* | 940 | /* |
937 | * Refresh credentials. XXX - finish | 941 | * Refresh credentials. XXX - finish |
938 | */ | 942 | */ |
939 | static int | 943 | static int |
940 | gss_refresh(struct rpc_task *task) | 944 | gss_refresh(struct rpc_task *task) |
941 | { | 945 | { |
946 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | ||
947 | int ret = 0; | ||
948 | |||
949 | if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && | ||
950 | !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) { | ||
951 | ret = gss_renew_cred(task); | ||
952 | if (ret < 0) | ||
953 | goto out; | ||
954 | cred = task->tk_msg.rpc_cred; | ||
955 | } | ||
942 | 956 | ||
943 | if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred)) | 957 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) |
944 | return gss_refresh_upcall(task); | 958 | ret = gss_refresh_upcall(task); |
945 | return 0; | 959 | out: |
960 | return ret; | ||
946 | } | 961 | } |
947 | 962 | ||
948 | /* Dummy refresh routine: used only when destroying the context */ | 963 | /* Dummy refresh routine: used only when destroying the context */ |