diff options
-rw-r--r-- | include/linux/sunrpc/auth.h | 5 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 17 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 25 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 6 |
4 files changed, 37 insertions, 16 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index b68c11a2d6dd..bfc5fb279539 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -50,6 +50,7 @@ struct rpc_cred { | |||
50 | }; | 50 | }; |
51 | #define RPCAUTH_CRED_LOCKED 0x0001 | 51 | #define RPCAUTH_CRED_LOCKED 0x0001 |
52 | #define RPCAUTH_CRED_UPTODATE 0x0002 | 52 | #define RPCAUTH_CRED_UPTODATE 0x0002 |
53 | #define RPCAUTH_CRED_NEW 0x0004 | ||
53 | 54 | ||
54 | #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 | 55 | #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 |
55 | 56 | ||
@@ -87,6 +88,10 @@ struct rpc_auth { | |||
87 | * uid/gid, fs[ug]id, gids) | 88 | * uid/gid, fs[ug]id, gids) |
88 | */ | 89 | */ |
89 | 90 | ||
91 | /* Flags for rpcauth_lookupcred() */ | ||
92 | #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ | ||
93 | #define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */ | ||
94 | |||
90 | /* | 95 | /* |
91 | * Client authentication ops | 96 | * Client authentication ops |
92 | */ | 97 | */ |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 9ac1b8c26c01..1ca89c36da7a 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -184,7 +184,7 @@ rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free) | |||
184 | */ | 184 | */ |
185 | struct rpc_cred * | 185 | struct rpc_cred * |
186 | rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | 186 | rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, |
187 | int taskflags) | 187 | int flags) |
188 | { | 188 | { |
189 | struct rpc_cred_cache *cache = auth->au_credcache; | 189 | struct rpc_cred_cache *cache = auth->au_credcache; |
190 | HLIST_HEAD(free); | 190 | HLIST_HEAD(free); |
@@ -193,7 +193,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
193 | *cred = NULL; | 193 | *cred = NULL; |
194 | int nr = 0; | 194 | int nr = 0; |
195 | 195 | ||
196 | if (!(taskflags & RPC_TASK_ROOTCREDS)) | 196 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) |
197 | nr = acred->uid & RPC_CREDCACHE_MASK; | 197 | nr = acred->uid & RPC_CREDCACHE_MASK; |
198 | retry: | 198 | retry: |
199 | spin_lock(&rpc_credcache_lock); | 199 | spin_lock(&rpc_credcache_lock); |
@@ -202,7 +202,7 @@ retry: | |||
202 | hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { | 202 | hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { |
203 | struct rpc_cred *entry; | 203 | struct rpc_cred *entry; |
204 | entry = hlist_entry(pos, struct rpc_cred, cr_hash); | 204 | entry = hlist_entry(pos, struct rpc_cred, cr_hash); |
205 | if (entry->cr_ops->crmatch(acred, entry, taskflags)) { | 205 | if (entry->cr_ops->crmatch(acred, entry, flags)) { |
206 | hlist_del(&entry->cr_hash); | 206 | hlist_del(&entry->cr_hash); |
207 | cred = entry; | 207 | cred = entry; |
208 | break; | 208 | break; |
@@ -224,7 +224,7 @@ retry: | |||
224 | rpcauth_destroy_credlist(&free); | 224 | rpcauth_destroy_credlist(&free); |
225 | 225 | ||
226 | if (!cred) { | 226 | if (!cred) { |
227 | new = auth->au_ops->crcreate(auth, acred, taskflags); | 227 | new = auth->au_ops->crcreate(auth, acred, flags); |
228 | if (!IS_ERR(new)) { | 228 | if (!IS_ERR(new)) { |
229 | #ifdef RPC_DEBUG | 229 | #ifdef RPC_DEBUG |
230 | new->cr_magic = RPCAUTH_CRED_MAGIC; | 230 | new->cr_magic = RPCAUTH_CRED_MAGIC; |
@@ -238,7 +238,7 @@ retry: | |||
238 | } | 238 | } |
239 | 239 | ||
240 | struct rpc_cred * | 240 | struct rpc_cred * |
241 | rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) | 241 | rpcauth_lookupcred(struct rpc_auth *auth, int flags) |
242 | { | 242 | { |
243 | struct auth_cred acred = { | 243 | struct auth_cred acred = { |
244 | .uid = current->fsuid, | 244 | .uid = current->fsuid, |
@@ -250,7 +250,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) | |||
250 | dprintk("RPC: looking up %s cred\n", | 250 | dprintk("RPC: looking up %s cred\n", |
251 | auth->au_ops->au_name); | 251 | auth->au_ops->au_name); |
252 | get_group_info(acred.group_info); | 252 | get_group_info(acred.group_info); |
253 | ret = auth->au_ops->lookup_cred(auth, &acred, taskflags); | 253 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); |
254 | put_group_info(acred.group_info); | 254 | put_group_info(acred.group_info); |
255 | return ret; | 255 | return ret; |
256 | } | 256 | } |
@@ -265,11 +265,14 @@ rpcauth_bindcred(struct rpc_task *task) | |||
265 | .group_info = current->group_info, | 265 | .group_info = current->group_info, |
266 | }; | 266 | }; |
267 | struct rpc_cred *ret; | 267 | struct rpc_cred *ret; |
268 | int flags = 0; | ||
268 | 269 | ||
269 | dprintk("RPC: %4d looking up %s cred\n", | 270 | dprintk("RPC: %4d looking up %s cred\n", |
270 | task->tk_pid, task->tk_auth->au_ops->au_name); | 271 | task->tk_pid, task->tk_auth->au_ops->au_name); |
271 | get_group_info(acred.group_info); | 272 | get_group_info(acred.group_info); |
272 | ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags); | 273 | if (task->tk_flags & RPC_TASK_ROOTCREDS) |
274 | flags |= RPCAUTH_LOOKUP_ROOTCREDS; | ||
275 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); | ||
273 | if (!IS_ERR(ret)) | 276 | if (!IS_ERR(ret)) |
274 | task->tk_msg.rpc_cred = ret; | 277 | task->tk_msg.rpc_cred = ret; |
275 | else | 278 | else |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8d782282ec19..03affcbf6292 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -158,6 +158,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | |||
158 | old = gss_cred->gc_ctx; | 158 | old = gss_cred->gc_ctx; |
159 | gss_cred->gc_ctx = ctx; | 159 | gss_cred->gc_ctx = ctx; |
160 | cred->cr_flags |= RPCAUTH_CRED_UPTODATE; | 160 | cred->cr_flags |= RPCAUTH_CRED_UPTODATE; |
161 | cred->cr_flags &= ~RPCAUTH_CRED_NEW; | ||
161 | write_unlock(&gss_ctx_lock); | 162 | write_unlock(&gss_ctx_lock); |
162 | if (old) | 163 | if (old) |
163 | gss_put_ctx(old); | 164 | gss_put_ctx(old); |
@@ -580,7 +581,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
580 | } else { | 581 | } else { |
581 | struct auth_cred acred = { .uid = uid }; | 582 | struct auth_cred acred = { .uid = uid }; |
582 | spin_unlock(&gss_auth->lock); | 583 | spin_unlock(&gss_auth->lock); |
583 | cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0); | 584 | cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); |
584 | if (IS_ERR(cred)) { | 585 | if (IS_ERR(cred)) { |
585 | err = PTR_ERR(cred); | 586 | err = PTR_ERR(cred); |
586 | goto err_put_ctx; | 587 | goto err_put_ctx; |
@@ -758,13 +759,13 @@ gss_destroy_cred(struct rpc_cred *rc) | |||
758 | * Lookup RPCSEC_GSS cred for the current process | 759 | * Lookup RPCSEC_GSS cred for the current process |
759 | */ | 760 | */ |
760 | static struct rpc_cred * | 761 | static struct rpc_cred * |
761 | gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) | 762 | gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
762 | { | 763 | { |
763 | return rpcauth_lookup_credcache(auth, acred, taskflags); | 764 | return rpcauth_lookup_credcache(auth, acred, flags); |
764 | } | 765 | } |
765 | 766 | ||
766 | static struct rpc_cred * | 767 | static struct rpc_cred * |
767 | gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) | 768 | gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
768 | { | 769 | { |
769 | struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 770 | struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
770 | struct gss_cred *cred = NULL; | 771 | struct gss_cred *cred = NULL; |
@@ -785,13 +786,17 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) | |||
785 | */ | 786 | */ |
786 | cred->gc_flags = 0; | 787 | cred->gc_flags = 0; |
787 | cred->gc_base.cr_ops = &gss_credops; | 788 | cred->gc_base.cr_ops = &gss_credops; |
789 | cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; | ||
788 | cred->gc_service = gss_auth->service; | 790 | cred->gc_service = gss_auth->service; |
791 | /* Is the caller prepared to initialise the credential? */ | ||
792 | if (flags & RPCAUTH_LOOKUP_NEW) | ||
793 | goto out; | ||
789 | do { | 794 | do { |
790 | err = gss_create_upcall(gss_auth, cred); | 795 | err = gss_create_upcall(gss_auth, cred); |
791 | } while (err == -EAGAIN); | 796 | } while (err == -EAGAIN); |
792 | if (err < 0) | 797 | if (err < 0) |
793 | goto out_err; | 798 | goto out_err; |
794 | 799 | out: | |
795 | return &cred->gc_base; | 800 | return &cred->gc_base; |
796 | 801 | ||
797 | out_err: | 802 | out_err: |
@@ -801,13 +806,21 @@ out_err: | |||
801 | } | 806 | } |
802 | 807 | ||
803 | static int | 808 | static int |
804 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags) | 809 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
805 | { | 810 | { |
806 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 811 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
807 | 812 | ||
813 | /* | ||
814 | * If the searchflags have set RPCAUTH_LOOKUP_NEW, then | ||
815 | * we don't really care if the credential has expired or not, | ||
816 | * since the caller should be prepared to reinitialise it. | ||
817 | */ | ||
818 | if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) | ||
819 | goto out; | ||
808 | /* Don't match with creds that have expired. */ | 820 | /* Don't match with creds that have expired. */ |
809 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 821 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) |
810 | return 0; | 822 | return 0; |
823 | out: | ||
811 | return (rc->cr_uid == acred->uid); | 824 | return (rc->cr_uid == acred->uid); |
812 | } | 825 | } |
813 | 826 | ||
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 1b3ed4fd1987..df14b6bfbf10 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -75,7 +75,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
75 | 75 | ||
76 | atomic_set(&cred->uc_count, 1); | 76 | atomic_set(&cred->uc_count, 1); |
77 | cred->uc_flags = RPCAUTH_CRED_UPTODATE; | 77 | cred->uc_flags = RPCAUTH_CRED_UPTODATE; |
78 | if (flags & RPC_TASK_ROOTCREDS) { | 78 | if (flags & RPCAUTH_LOOKUP_ROOTCREDS) { |
79 | cred->uc_uid = 0; | 79 | cred->uc_uid = 0; |
80 | cred->uc_gid = 0; | 80 | cred->uc_gid = 0; |
81 | cred->uc_gids[0] = NOGROUP; | 81 | cred->uc_gids[0] = NOGROUP; |
@@ -108,12 +108,12 @@ unx_destroy_cred(struct rpc_cred *cred) | |||
108 | * request root creds (e.g. for NFS swapping). | 108 | * request root creds (e.g. for NFS swapping). |
109 | */ | 109 | */ |
110 | static int | 110 | static int |
111 | unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags) | 111 | unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) |
112 | { | 112 | { |
113 | struct unx_cred *cred = (struct unx_cred *) rcred; | 113 | struct unx_cred *cred = (struct unx_cred *) rcred; |
114 | int i; | 114 | int i; |
115 | 115 | ||
116 | if (!(taskflags & RPC_TASK_ROOTCREDS)) { | 116 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) { |
117 | int groups; | 117 | int groups; |
118 | 118 | ||
119 | if (cred->uc_uid != acred->uid | 119 | if (cred->uc_uid != acred->uid |