Blame view
net/sunrpc/auth_gss/auth_gss.c
53.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
f30c22695 fix file specific... |
2 |
* linux/net/sunrpc/auth_gss/auth_gss.c |
1da177e4c Linux-2.6.12-rc2 |
3 4 |
* * RPCSEC_GSS client authentication. |
cca5172a7 [NET] SUNRPC: Fix... |
5 |
* |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
* Copyright (c) 2000 The Regents of the University of Michigan. * All rights reserved. * * Dug Song <dugsong@monkey.org> * Andy Adamson <andros@umich.edu> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
1da177e4c Linux-2.6.12-rc2 |
36 37 38 39 40 41 42 |
*/ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
43 |
#include <linux/sched.h> |
2d2da60c6 RPCSEC_GSS: clien... |
44 |
#include <linux/pagemap.h> |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 49 50 51 52 |
#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/auth.h> #include <linux/sunrpc/auth_gss.h> #include <linux/sunrpc/svcauth_gss.h> #include <linux/sunrpc/gss_err.h> #include <linux/workqueue.h> #include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/gss_api.h> |
7c0f6ba68 Replace <asm/uacc... |
53 |
#include <linux/uaccess.h> |
eb6dc19d8 RPCSEC_GSS: Share... |
54 |
#include <linux/hashtable.h> |
1da177e4c Linux-2.6.12-rc2 |
55 |
|
abfdbd53a SUNRPC: Faster de... |
56 |
#include "../netns.h" |
f1c0a8615 SUNRPC: Mark auth... |
57 |
static const struct rpc_authops authgss_ops; |
1da177e4c Linux-2.6.12-rc2 |
58 |
|
f1c0a8615 SUNRPC: Mark auth... |
59 |
static const struct rpc_credops gss_credops; |
0df7fb74f SUNRPC: Ensure RP... |
60 |
static const struct rpc_credops gss_nullops; |
1da177e4c Linux-2.6.12-rc2 |
61 |
|
126e216a8 SUNRPC: Don't spa... |
62 63 |
#define GSS_RETRY_EXPIRED 5 static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; |
4de6caa27 SUNRPC new rpc_cr... |
64 65 |
#define GSS_KEY_EXPIRE_TIMEO 240 static unsigned int gss_key_expire_timeo = GSS_KEY_EXPIRE_TIMEO; |
f895b252d sunrpc: eliminate... |
66 |
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
1da177e4c Linux-2.6.12-rc2 |
67 68 |
# define RPCDBG_FACILITY RPCDBG_AUTH #endif |
725f2865d gss_krb5: Introdu... |
69 |
#define GSS_CRED_SLACK (RPC_MAX_AUTH_SIZE * 2) |
1da177e4c Linux-2.6.12-rc2 |
70 71 |
/* length of a krb5 verifier (48), plus data added before arguments when * using integrity (two 4-byte integers): */ |
adeb8133d rpc: spkm3 update |
72 |
#define GSS_VERF_SLACK 100 |
1da177e4c Linux-2.6.12-rc2 |
73 |
|
23c323af0 SUNRPC: No, I did... |
74 |
static DEFINE_HASHTABLE(gss_auth_hash_table, 4); |
eb6dc19d8 RPCSEC_GSS: Share... |
75 |
static DEFINE_SPINLOCK(gss_auth_hash_lock); |
191722843 RPCSEC_GSS: Switc... |
76 77 78 79 80 |
struct gss_pipe { struct rpc_pipe_dir_object pdo; struct rpc_pipe *pipe; struct rpc_clnt *clnt; const char *name; |
414a62959 RPCSEC_GSS: Share... |
81 |
struct kref kref; |
191722843 RPCSEC_GSS: Switc... |
82 |
}; |
1da177e4c Linux-2.6.12-rc2 |
83 |
struct gss_auth { |
0285ed1f1 SUNRPC: Ensure th... |
84 |
struct kref kref; |
eb6dc19d8 RPCSEC_GSS: Share... |
85 |
struct hlist_node hash; |
1da177e4c Linux-2.6.12-rc2 |
86 87 88 |
struct rpc_auth rpc_auth; struct gss_api_mech *mech; enum rpc_gss_svc service; |
1da177e4c Linux-2.6.12-rc2 |
89 |
struct rpc_clnt *client; |
e726340ac RPCSEC_GSS: Furth... |
90 |
struct net *net; |
34769fc48 rpc: implement ne... |
91 92 93 94 95 96 |
/* * There are two upcall pipes; dentry[1], named "gssd", is used * for the new text-based upcall; dentry[0] is named after the * mechanism (for example, "krb5") and exists for * backwards-compatibility with older gssd's. */ |
191722843 RPCSEC_GSS: Switc... |
97 |
struct gss_pipe *gss_pipe[2]; |
bd4a3eb15 RPCSEC_GSS: Clean... |
98 |
const char *target_name; |
1da177e4c Linux-2.6.12-rc2 |
99 |
}; |
79a3f20b6 rpc: use count of... |
100 |
/* pipe_version >= 0 if and only if someone has a pipe open. */ |
79a3f20b6 rpc: use count of... |
101 102 103 |
static DEFINE_SPINLOCK(pipe_version_lock); static struct rpc_wait_queue pipe_version_rpc_waitqueue; static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); |
9eb2ddb48 SUNRPC: Ensure th... |
104 |
static void gss_put_auth(struct gss_auth *gss_auth); |
cf81939d6 rpc: track number... |
105 |
|
5d28dc820 SUNRPC: Convert g... |
106 |
static void gss_free_ctx(struct gss_cl_ctx *); |
b693ba4a3 SUNRPC: Constify ... |
107 108 |
static const struct rpc_pipe_ops gss_upcall_ops_v0; static const struct rpc_pipe_ops gss_upcall_ops_v1; |
1da177e4c Linux-2.6.12-rc2 |
109 |
|
1da177e4c Linux-2.6.12-rc2 |
110 111 112 |
static inline struct gss_cl_ctx * gss_get_ctx(struct gss_cl_ctx *ctx) { |
0fa104726 net, sunrpc: conv... |
113 |
refcount_inc(&ctx->count); |
1da177e4c Linux-2.6.12-rc2 |
114 115 116 117 118 119 |
return ctx; } static inline void gss_put_ctx(struct gss_cl_ctx *ctx) { |
0fa104726 net, sunrpc: conv... |
120 |
if (refcount_dec_and_test(&ctx->count)) |
5d28dc820 SUNRPC: Convert g... |
121 |
gss_free_ctx(ctx); |
1da177e4c Linux-2.6.12-rc2 |
122 |
} |
5d28dc820 SUNRPC: Convert g... |
123 124 125 |
/* gss_cred_set_ctx: * called by gss_upcall_callback and gss_create_upcall in order * to set the gss context. The actual exchange of an old context |
9beae4677 SUNRPC: cleanup G... |
126 |
* and a new one is protected by the pipe->lock. |
5d28dc820 SUNRPC: Convert g... |
127 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
128 129 130 131 |
static void gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) { struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
5d28dc820 SUNRPC: Convert g... |
132 |
|
cd019f751 SUNRPC: Don't cha... |
133 134 |
if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) return; |
7b6962b0a SUNRPC: Fix a rac... |
135 |
gss_get_ctx(ctx); |
cf778b00e net: reintroduce ... |
136 |
rcu_assign_pointer(gss_cred->gc_ctx, ctx); |
fc432dd90 SUNRPC: Enforce a... |
137 |
set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
4e857c58e arch: Mass conver... |
138 |
smp_mb__before_atomic(); |
fc432dd90 SUNRPC: Enforce a... |
139 |
clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); |
1da177e4c Linux-2.6.12-rc2 |
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
} static const void * simple_get_bytes(const void *p, const void *end, void *res, size_t len) { const void *q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); memcpy(res, p, len); return q; } static inline const void * simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest) { const void *q; unsigned int len; p = simple_get_bytes(p, end, &len, sizeof(len)); if (IS_ERR(p)) return p; q = (const void *)((const char *)p + len); if (unlikely(q > end || q < p)) return ERR_PTR(-EFAULT); |
0f38b873a SUNRPC: Use GFP_N... |
164 |
dest->data = kmemdup(p, len, GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
165 166 167 |
if (unlikely(dest->data == NULL)) return ERR_PTR(-ENOMEM); dest->len = len; |
1da177e4c Linux-2.6.12-rc2 |
168 169 170 171 172 173 174 175 |
return q; } static struct gss_cl_ctx * gss_cred_get_ctx(struct rpc_cred *cred) { struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_cl_ctx *ctx = NULL; |
5d28dc820 SUNRPC: Convert g... |
176 |
rcu_read_lock(); |
c5e6aecd0 sunrpc: fix RCU h... |
177 178 179 |
ctx = rcu_dereference(gss_cred->gc_ctx); if (ctx) gss_get_ctx(ctx); |
5d28dc820 SUNRPC: Convert g... |
180 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
181 182 183 184 185 186 187 |
return ctx; } static struct gss_cl_ctx * gss_alloc_context(void) { struct gss_cl_ctx *ctx; |
0f38b873a SUNRPC: Use GFP_N... |
188 |
ctx = kzalloc(sizeof(*ctx), GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
189 |
if (ctx != NULL) { |
1da177e4c Linux-2.6.12-rc2 |
190 191 192 |
ctx->gc_proc = RPC_GSS_PROC_DATA; ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */ spin_lock_init(&ctx->gc_seq_lock); |
0fa104726 net, sunrpc: conv... |
193 |
refcount_set(&ctx->count,1); |
1da177e4c Linux-2.6.12-rc2 |
194 195 196 197 198 199 200 201 202 203 204 |
} return ctx; } #define GSSD_MIN_TIMEOUT (60 * 60) static const void * gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm) { const void *q; unsigned int seclen; unsigned int timeout; |
620038f6d SUNRPC set gss gc... |
205 |
unsigned long now = jiffies; |
1da177e4c Linux-2.6.12-rc2 |
206 207 |
u32 window_size; int ret; |
620038f6d SUNRPC set gss gc... |
208 209 210 211 |
/* First unsigned int gives the remaining lifetime in seconds of the * credential - e.g. the remaining TGT lifetime for Kerberos or * the -t value passed to GSSD. */ |
1da177e4c Linux-2.6.12-rc2 |
212 213 214 215 216 |
p = simple_get_bytes(p, end, &timeout, sizeof(timeout)); if (IS_ERR(p)) goto err; if (timeout == 0) timeout = GSSD_MIN_TIMEOUT; |
620038f6d SUNRPC set gss gc... |
217 218 219 220 |
ctx->gc_expiry = now + ((unsigned long)timeout * HZ); /* Sequence number window. Determines the maximum number of * simultaneous requests */ |
1da177e4c Linux-2.6.12-rc2 |
221 222 223 224 225 226 |
p = simple_get_bytes(p, end, &window_size, sizeof(window_size)); if (IS_ERR(p)) goto err; ctx->gc_win = window_size; /* gssd signals an error by passing ctx->gc_win = 0: */ if (ctx->gc_win == 0) { |
dc5ddce95 sunrpc: parse and... |
227 228 229 230 231 232 233 234 |
/* * in which case, p points to an error code. Anything other * than -EKEYEXPIRED gets converted to -EACCES. */ p = simple_get_bytes(p, end, &ret, sizeof(ret)); if (!IS_ERR(p)) p = (ret == -EKEYEXPIRED) ? ERR_PTR(-EKEYEXPIRED) : ERR_PTR(-EACCES); |
1da177e4c Linux-2.6.12-rc2 |
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
goto err; } /* copy the opaque wire context */ p = simple_get_netobj(p, end, &ctx->gc_wire_ctx); if (IS_ERR(p)) goto err; /* import the opaque security context */ p = simple_get_bytes(p, end, &seclen, sizeof(seclen)); if (IS_ERR(p)) goto err; q = (const void *)((const char *)p + seclen); if (unlikely(q > end || q < p)) { p = ERR_PTR(-EFAULT); goto err; } |
400f26b54 SUNRPC: condition... |
250 |
ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, NULL, GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
251 252 253 254 |
if (ret < 0) { p = ERR_PTR(ret); goto err; } |
2004c726b auth_gss: fetch t... |
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
/* is there any trailing data? */ if (q == end) { p = q; goto done; } /* pull in acceptor name (if there is one) */ p = simple_get_netobj(q, end, &ctx->gc_acceptor); if (IS_ERR(p)) goto err; done: dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u acceptor %.*s ", __func__, ctx->gc_expiry, now, timeout, ctx->gc_acceptor.len, ctx->gc_acceptor.data); return p; |
1da177e4c Linux-2.6.12-rc2 |
272 |
err: |
173db3093 sunrpc: silence b... |
273 274 |
dprintk("RPC: %s returns error %ld ", __func__, -PTR_ERR(p)); |
1da177e4c Linux-2.6.12-rc2 |
275 276 |
return p; } |
34769fc48 rpc: implement ne... |
277 |
#define UPCALL_BUF_LEN 128 |
1da177e4c Linux-2.6.12-rc2 |
278 279 |
struct gss_upcall_msg { |
7ff139696 net, sunrpc: conv... |
280 |
refcount_t count; |
7eaf040b7 sunrpc: Use kuid_... |
281 |
kuid_t uid; |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 |
struct rpc_pipe_msg msg; struct list_head list; struct gss_auth *auth; |
9beae4677 SUNRPC: cleanup G... |
285 |
struct rpc_pipe *pipe; |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 |
struct rpc_wait_queue rpc_waitqueue; wait_queue_head_t waitqueue; struct gss_cl_ctx *ctx; |
34769fc48 rpc: implement ne... |
289 |
char databuf[UPCALL_BUF_LEN]; |
1da177e4c Linux-2.6.12-rc2 |
290 |
}; |
2aed8b476 SUNRPC: Convert a... |
291 |
static int get_pipe_version(struct net *net) |
79a3f20b6 rpc: use count of... |
292 |
{ |
2aed8b476 SUNRPC: Convert a... |
293 |
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
79a3f20b6 rpc: use count of... |
294 295 296 |
int ret; spin_lock(&pipe_version_lock); |
2aed8b476 SUNRPC: Convert a... |
297 298 299 |
if (sn->pipe_version >= 0) { atomic_inc(&sn->pipe_users); ret = sn->pipe_version; |
79a3f20b6 rpc: use count of... |
300 301 302 303 304 |
} else ret = -EAGAIN; spin_unlock(&pipe_version_lock); return ret; } |
2aed8b476 SUNRPC: Convert a... |
305 |
static void put_pipe_version(struct net *net) |
79a3f20b6 rpc: use count of... |
306 |
{ |
2aed8b476 SUNRPC: Convert a... |
307 308 309 310 |
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) { sn->pipe_version = -1; |
79a3f20b6 rpc: use count of... |
311 312 313 |
spin_unlock(&pipe_version_lock); } } |
1da177e4c Linux-2.6.12-rc2 |
314 315 316 |
static void gss_release_msg(struct gss_upcall_msg *gss_msg) { |
e726340ac RPCSEC_GSS: Furth... |
317 |
struct net *net = gss_msg->auth->net; |
7ff139696 net, sunrpc: conv... |
318 |
if (!refcount_dec_and_test(&gss_msg->count)) |
1da177e4c Linux-2.6.12-rc2 |
319 |
return; |
2aed8b476 SUNRPC: Convert a... |
320 |
put_pipe_version(net); |
1da177e4c Linux-2.6.12-rc2 |
321 322 323 |
BUG_ON(!list_empty(&gss_msg->list)); if (gss_msg->ctx != NULL) gss_put_ctx(gss_msg->ctx); |
f6a1cc893 SUNRPC: Add a (em... |
324 |
rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); |
9eb2ddb48 SUNRPC: Ensure th... |
325 |
gss_put_auth(gss_msg->auth); |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 329 |
kfree(gss_msg); } static struct gss_upcall_msg * |
9130b8dbc SUNRPC: allow for... |
330 |
__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth) |
1da177e4c Linux-2.6.12-rc2 |
331 332 |
{ struct gss_upcall_msg *pos; |
9beae4677 SUNRPC: cleanup G... |
333 |
list_for_each_entry(pos, &pipe->in_downcall, list) { |
0b4d51b02 sunrpc: Use uid_e... |
334 |
if (!uid_eq(pos->uid, uid)) |
1da177e4c Linux-2.6.12-rc2 |
335 |
continue; |
9130b8dbc SUNRPC: allow for... |
336 337 |
if (auth && pos->auth->service != auth->service) continue; |
7ff139696 net, sunrpc: conv... |
338 |
refcount_inc(&pos->count); |
632f0d050 SUNRPC: Use __fun... |
339 340 |
dprintk("RPC: %s found msg %p ", __func__, pos); |
1da177e4c Linux-2.6.12-rc2 |
341 342 |
return pos; } |
632f0d050 SUNRPC: Use __fun... |
343 344 |
dprintk("RPC: %s found nothing ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
345 346 |
return NULL; } |
720b8f2d6 rpc: eliminate un... |
347 |
/* Try to add an upcall to the pipefs queue. |
1da177e4c Linux-2.6.12-rc2 |
348 349 350 351 |
* If an upcall owned by our uid already exists, then we return a reference * to that upcall instead of adding the new upcall. */ static inline struct gss_upcall_msg * |
053e324f6 rpc: remove unnee... |
352 |
gss_add_msg(struct gss_upcall_msg *gss_msg) |
1da177e4c Linux-2.6.12-rc2 |
353 |
{ |
9beae4677 SUNRPC: cleanup G... |
354 |
struct rpc_pipe *pipe = gss_msg->pipe; |
1da177e4c Linux-2.6.12-rc2 |
355 |
struct gss_upcall_msg *old; |
9beae4677 SUNRPC: cleanup G... |
356 |
spin_lock(&pipe->lock); |
9130b8dbc SUNRPC: allow for... |
357 |
old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth); |
1da177e4c Linux-2.6.12-rc2 |
358 |
if (old == NULL) { |
7ff139696 net, sunrpc: conv... |
359 |
refcount_inc(&gss_msg->count); |
9beae4677 SUNRPC: cleanup G... |
360 |
list_add(&gss_msg->list, &pipe->in_downcall); |
1da177e4c Linux-2.6.12-rc2 |
361 362 |
} else gss_msg = old; |
9beae4677 SUNRPC: cleanup G... |
363 |
spin_unlock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
364 365 366 367 368 369 |
return gss_msg; } static void __gss_unhash_msg(struct gss_upcall_msg *gss_msg) { |
1da177e4c Linux-2.6.12-rc2 |
370 371 372 |
list_del_init(&gss_msg->list); rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); wake_up_all(&gss_msg->waitqueue); |
7ff139696 net, sunrpc: conv... |
373 |
refcount_dec(&gss_msg->count); |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 377 378 |
} static void gss_unhash_msg(struct gss_upcall_msg *gss_msg) { |
9beae4677 SUNRPC: cleanup G... |
379 |
struct rpc_pipe *pipe = gss_msg->pipe; |
1da177e4c Linux-2.6.12-rc2 |
380 |
|
3b68aaeaf SUNRPC: Always ma... |
381 382 |
if (list_empty(&gss_msg->list)) return; |
9beae4677 SUNRPC: cleanup G... |
383 |
spin_lock(&pipe->lock); |
3b68aaeaf SUNRPC: Always ma... |
384 385 |
if (!list_empty(&gss_msg->list)) __gss_unhash_msg(gss_msg); |
9beae4677 SUNRPC: cleanup G... |
386 |
spin_unlock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
387 388 389 |
} static void |
126e216a8 SUNRPC: Don't spa... |
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg) { switch (gss_msg->msg.errno) { case 0: if (gss_msg->ctx == NULL) break; clear_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags); gss_cred_set_ctx(&gss_cred->gc_base, gss_msg->ctx); break; case -EKEYEXPIRED: set_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags); } gss_cred->gc_upcall_timestamp = jiffies; gss_cred->gc_upcall = NULL; rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); } static void |
1da177e4c Linux-2.6.12-rc2 |
408 409 |
gss_upcall_callback(struct rpc_task *task) { |
a17c2153d SUNRPC: Move the ... |
410 |
struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, |
1da177e4c Linux-2.6.12-rc2 |
411 412 |
struct gss_cred, gc_base); struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
9beae4677 SUNRPC: cleanup G... |
413 |
struct rpc_pipe *pipe = gss_msg->pipe; |
1da177e4c Linux-2.6.12-rc2 |
414 |
|
9beae4677 SUNRPC: cleanup G... |
415 |
spin_lock(&pipe->lock); |
126e216a8 SUNRPC: Don't spa... |
416 |
gss_handle_downcall_result(gss_cred, gss_msg); |
9beae4677 SUNRPC: cleanup G... |
417 |
spin_unlock(&pipe->lock); |
126e216a8 SUNRPC: Don't spa... |
418 |
task->tk_status = gss_msg->msg.errno; |
1da177e4c Linux-2.6.12-rc2 |
419 420 |
gss_release_msg(gss_msg); } |
34769fc48 rpc: implement ne... |
421 422 |
static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) { |
90602c7b1 sunrpc: Update gs... |
423 424 425 426 |
uid_t uid = from_kuid(&init_user_ns, gss_msg->uid); memcpy(gss_msg->databuf, &uid, sizeof(uid)); gss_msg->msg.data = gss_msg->databuf; gss_msg->msg.len = sizeof(uid); |
9d3a2260f SUNRPC: Fix buffe... |
427 428 |
BUILD_BUG_ON(sizeof(uid) > sizeof(gss_msg->databuf)); |
34769fc48 rpc: implement ne... |
429 |
} |
9d3a2260f SUNRPC: Fix buffe... |
430 |
static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, |
bd4a3eb15 RPCSEC_GSS: Clean... |
431 432 |
const char *service_name, const char *target_name) |
34769fc48 rpc: implement ne... |
433 |
{ |
683ac6656 gss_krb5: Add upc... |
434 |
struct gss_api_mech *mech = gss_msg->auth->mech; |
8b1c7bf5b rpc: add target f... |
435 |
char *p = gss_msg->databuf; |
9d3a2260f SUNRPC: Fix buffe... |
436 437 438 439 440 441 442 443 |
size_t buflen = sizeof(gss_msg->databuf); int len; len = scnprintf(p, buflen, "mech=%s uid=%d ", mech->gm_name, from_kuid(&init_user_ns, gss_msg->uid)); buflen -= len; p += len; gss_msg->msg.len = len; |
bd4a3eb15 RPCSEC_GSS: Clean... |
444 |
if (target_name) { |
9d3a2260f SUNRPC: Fix buffe... |
445 446 |
len = scnprintf(p, buflen, "target=%s ", target_name); buflen -= len; |
8b1c7bf5b rpc: add target f... |
447 448 449 |
p += len; gss_msg->msg.len += len; } |
68c97153f SUNRPC: Clean up ... |
450 |
if (service_name != NULL) { |
9d3a2260f SUNRPC: Fix buffe... |
451 452 |
len = scnprintf(p, buflen, "service=%s ", service_name); buflen -= len; |
2efef7080 rpc: add service ... |
453 454 455 |
p += len; gss_msg->msg.len += len; } |
683ac6656 gss_krb5: Add upc... |
456 |
if (mech->gm_upcall_enctypes) { |
9d3a2260f SUNRPC: Fix buffe... |
457 458 459 |
len = scnprintf(p, buflen, "enctypes=%s ", mech->gm_upcall_enctypes); buflen -= len; |
683ac6656 gss_krb5: Add upc... |
460 461 462 |
p += len; gss_msg->msg.len += len; } |
9d3a2260f SUNRPC: Fix buffe... |
463 464 465 466 |
len = scnprintf(p, buflen, " "); if (len == 0) goto out_overflow; |
8b1c7bf5b rpc: add target f... |
467 |
gss_msg->msg.len += len; |
34769fc48 rpc: implement ne... |
468 |
gss_msg->msg.data = gss_msg->databuf; |
9d3a2260f SUNRPC: Fix buffe... |
469 470 471 472 |
return 0; out_overflow: WARN_ON_ONCE(1); return -ENOMEM; |
34769fc48 rpc: implement ne... |
473 |
} |
68c97153f SUNRPC: Clean up ... |
474 |
static struct gss_upcall_msg * |
e726340ac RPCSEC_GSS: Furth... |
475 |
gss_alloc_msg(struct gss_auth *gss_auth, |
7eaf040b7 sunrpc: Use kuid_... |
476 |
kuid_t uid, const char *service_name) |
1da177e4c Linux-2.6.12-rc2 |
477 478 |
{ struct gss_upcall_msg *gss_msg; |
79a3f20b6 rpc: use count of... |
479 |
int vers; |
9d3a2260f SUNRPC: Fix buffe... |
480 |
int err = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
481 |
|
0f38b873a SUNRPC: Use GFP_N... |
482 |
gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
db75b3d6b rpc: minor gss_al... |
483 |
if (gss_msg == NULL) |
9d3a2260f SUNRPC: Fix buffe... |
484 |
goto err; |
e726340ac RPCSEC_GSS: Furth... |
485 |
vers = get_pipe_version(gss_auth->net); |
9d3a2260f SUNRPC: Fix buffe... |
486 487 488 |
err = vers; if (err < 0) goto err_free_msg; |
191722843 RPCSEC_GSS: Switc... |
489 |
gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe; |
db75b3d6b rpc: minor gss_al... |
490 491 492 |
INIT_LIST_HEAD(&gss_msg->list); rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); init_waitqueue_head(&gss_msg->waitqueue); |
7ff139696 net, sunrpc: conv... |
493 |
refcount_set(&gss_msg->count, 1); |
db75b3d6b rpc: minor gss_al... |
494 495 |
gss_msg->uid = uid; gss_msg->auth = gss_auth; |
bd4a3eb15 RPCSEC_GSS: Clean... |
496 497 498 |
switch (vers) { case 0: gss_encode_v0_msg(gss_msg); |
5fccc5b52 SUNRPC: gss_alloc... |
499 |
break; |
bd4a3eb15 RPCSEC_GSS: Clean... |
500 |
default: |
9d3a2260f SUNRPC: Fix buffe... |
501 502 |
err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); if (err) |
e9776d0f4 SUNRPC: Fix a pip... |
503 |
goto err_put_pipe_version; |
bd4a3eb15 RPCSEC_GSS: Clean... |
504 |
}; |
9eb2ddb48 SUNRPC: Ensure th... |
505 |
kref_get(&gss_auth->kref); |
1da177e4c Linux-2.6.12-rc2 |
506 |
return gss_msg; |
e9776d0f4 SUNRPC: Fix a pip... |
507 508 |
err_put_pipe_version: put_pipe_version(gss_auth->net); |
9d3a2260f SUNRPC: Fix buffe... |
509 510 511 512 |
err_free_msg: kfree(gss_msg); err: return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
513 514 515 |
} static struct gss_upcall_msg * |
e726340ac RPCSEC_GSS: Furth... |
516 |
gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
517 |
{ |
7c67db3a8 NFSv4: Reintroduc... |
518 519 |
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1da177e4c Linux-2.6.12-rc2 |
520 |
struct gss_upcall_msg *gss_new, *gss_msg; |
7eaf040b7 sunrpc: Use kuid_... |
521 |
kuid_t uid = cred->cr_uid; |
1da177e4c Linux-2.6.12-rc2 |
522 |
|
e726340ac RPCSEC_GSS: Furth... |
523 |
gss_new = gss_alloc_msg(gss_auth, uid, gss_cred->gc_principal); |
db75b3d6b rpc: minor gss_al... |
524 525 |
if (IS_ERR(gss_new)) return gss_new; |
053e324f6 rpc: remove unnee... |
526 |
gss_msg = gss_add_msg(gss_new); |
1da177e4c Linux-2.6.12-rc2 |
527 |
if (gss_msg == gss_new) { |
1cded9d29 SUNRPC: fix refco... |
528 |
int res; |
7ff139696 net, sunrpc: conv... |
529 |
refcount_inc(&gss_msg->count); |
1cded9d29 SUNRPC: fix refco... |
530 |
res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); |
1da177e4c Linux-2.6.12-rc2 |
531 532 |
if (res) { gss_unhash_msg(gss_new); |
7ff139696 net, sunrpc: conv... |
533 |
refcount_dec(&gss_msg->count); |
1cded9d29 SUNRPC: fix refco... |
534 |
gss_release_msg(gss_new); |
1da177e4c Linux-2.6.12-rc2 |
535 536 537 538 539 540 |
gss_msg = ERR_PTR(res); } } else gss_release_msg(gss_new); return gss_msg; } |
b03568c32 rpc: factor out w... |
541 542 |
static void warn_gssd(void) { |
0ea9de0ea sunrpc: turn warn... |
543 544 |
dprintk("AUTH_GSS upcall failed. Please check user daemon is running. "); |
b03568c32 rpc: factor out w... |
545 |
} |
1da177e4c Linux-2.6.12-rc2 |
546 547 548 |
static inline int gss_refresh_upcall(struct rpc_task *task) { |
a17c2153d SUNRPC: Move the ... |
549 |
struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
4a8c1344d SUNRPC: Add a bac... |
550 |
struct gss_auth *gss_auth = container_of(cred->cr_auth, |
1da177e4c Linux-2.6.12-rc2 |
551 552 553 554 |
struct gss_auth, rpc_auth); struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_upcall_msg *gss_msg; |
9beae4677 SUNRPC: cleanup G... |
555 |
struct rpc_pipe *pipe; |
1da177e4c Linux-2.6.12-rc2 |
556 |
int err = 0; |
632f0d050 SUNRPC: Use __fun... |
557 558 |
dprintk("RPC: %5u %s for uid %u ", |
cdba321e2 sunrpc: Convert k... |
559 |
task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
e726340ac RPCSEC_GSS: Furth... |
560 |
gss_msg = gss_setup_upcall(gss_auth, cred); |
480e3243d SUNRPC: IS_ERR/PT... |
561 |
if (PTR_ERR(gss_msg) == -EAGAIN) { |
79a3f20b6 rpc: use count of... |
562 563 564 565 566 |
/* XXX: warning on the first, under the assumption we * shouldn't normally hit this case on a refresh. */ warn_gssd(); task->tk_timeout = 15*HZ; rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL); |
d1a8016a2 NFS: Fix infinite... |
567 |
return -EAGAIN; |
79a3f20b6 rpc: use count of... |
568 |
} |
1da177e4c Linux-2.6.12-rc2 |
569 570 571 572 |
if (IS_ERR(gss_msg)) { err = PTR_ERR(gss_msg); goto out; } |
9beae4677 SUNRPC: cleanup G... |
573 574 |
pipe = gss_msg->pipe; spin_lock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
575 |
if (gss_cred->gc_upcall != NULL) |
5d00837b9 SUNRPC: Run rpc t... |
576 |
rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); |
126e216a8 SUNRPC: Don't spa... |
577 |
else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { |
1da177e4c Linux-2.6.12-rc2 |
578 579 580 |
task->tk_timeout = 0; gss_cred->gc_upcall = gss_msg; /* gss_upcall_callback will release the reference to gss_upcall_msg */ |
7ff139696 net, sunrpc: conv... |
581 |
refcount_inc(&gss_msg->count); |
5d00837b9 SUNRPC: Run rpc t... |
582 |
rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); |
126e216a8 SUNRPC: Don't spa... |
583 584 |
} else { gss_handle_downcall_result(gss_cred, gss_msg); |
1da177e4c Linux-2.6.12-rc2 |
585 |
err = gss_msg->msg.errno; |
126e216a8 SUNRPC: Don't spa... |
586 |
} |
9beae4677 SUNRPC: cleanup G... |
587 |
spin_unlock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
588 589 |
gss_release_msg(gss_msg); out: |
632f0d050 SUNRPC: Use __fun... |
590 591 |
dprintk("RPC: %5u %s for uid %u result %d ", |
cdba321e2 sunrpc: Convert k... |
592 593 |
task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid), err); |
1da177e4c Linux-2.6.12-rc2 |
594 595 596 597 598 599 |
return err; } static inline int gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) { |
e726340ac RPCSEC_GSS: Furth... |
600 |
struct net *net = gss_auth->net; |
abfdbd53a SUNRPC: Faster de... |
601 |
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
9beae4677 SUNRPC: cleanup G... |
602 |
struct rpc_pipe *pipe; |
1da177e4c Linux-2.6.12-rc2 |
603 604 605 |
struct rpc_cred *cred = &gss_cred->gc_base; struct gss_upcall_msg *gss_msg; DEFINE_WAIT(wait); |
d36ccb9ce SUNRPC: Fix a bug... |
606 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
607 |
|
cdba321e2 sunrpc: Convert k... |
608 609 610 |
dprintk("RPC: %s for uid %u ", __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
79a3f20b6 rpc: use count of... |
611 |
retry: |
d36ccb9ce SUNRPC: Fix a bug... |
612 |
err = 0; |
89f842435 sunrpc: replace s... |
613 614 615 616 617 |
/* if gssd is down, just skip upcalling altogether */ if (!gssd_running(net)) { warn_gssd(); return -EACCES; } |
e726340ac RPCSEC_GSS: Furth... |
618 |
gss_msg = gss_setup_upcall(gss_auth, cred); |
79a3f20b6 rpc: use count of... |
619 620 |
if (PTR_ERR(gss_msg) == -EAGAIN) { err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
89f842435 sunrpc: replace s... |
621 |
sn->pipe_version >= 0, 15 * HZ); |
2aed8b476 SUNRPC: Convert a... |
622 |
if (sn->pipe_version < 0) { |
d1a8016a2 NFS: Fix infinite... |
623 624 625 |
warn_gssd(); err = -EACCES; } |
d36ccb9ce SUNRPC: Fix a bug... |
626 |
if (err < 0) |
79a3f20b6 rpc: use count of... |
627 |
goto out; |
79a3f20b6 rpc: use count of... |
628 629 |
goto retry; } |
1da177e4c Linux-2.6.12-rc2 |
630 631 632 633 |
if (IS_ERR(gss_msg)) { err = PTR_ERR(gss_msg); goto out; } |
9beae4677 SUNRPC: cleanup G... |
634 |
pipe = gss_msg->pipe; |
1da177e4c Linux-2.6.12-rc2 |
635 |
for (;;) { |
5afa9133c SUNRPC: Ensure th... |
636 |
prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); |
9beae4677 SUNRPC: cleanup G... |
637 |
spin_lock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
638 |
if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { |
1da177e4c Linux-2.6.12-rc2 |
639 640 |
break; } |
9beae4677 SUNRPC: cleanup G... |
641 |
spin_unlock(&pipe->lock); |
5afa9133c SUNRPC: Ensure th... |
642 |
if (fatal_signal_pending(current)) { |
1da177e4c Linux-2.6.12-rc2 |
643 644 645 646 647 648 |
err = -ERESTARTSYS; goto out_intr; } schedule(); } if (gss_msg->ctx) |
7b6962b0a SUNRPC: Fix a rac... |
649 |
gss_cred_set_ctx(cred, gss_msg->ctx); |
1da177e4c Linux-2.6.12-rc2 |
650 651 |
else err = gss_msg->msg.errno; |
9beae4677 SUNRPC: cleanup G... |
652 |
spin_unlock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
653 654 655 656 |
out_intr: finish_wait(&gss_msg->waitqueue, &wait); gss_release_msg(gss_msg); out: |
632f0d050 SUNRPC: Use __fun... |
657 658 |
dprintk("RPC: %s for uid %u result %d ", |
cdba321e2 sunrpc: Convert k... |
659 |
__func__, from_kuid(&init_user_ns, cred->cr_uid), err); |
1da177e4c Linux-2.6.12-rc2 |
660 661 |
return err; } |
1da177e4c Linux-2.6.12-rc2 |
662 663 664 665 666 667 668 |
#define MSG_BUF_MAXSIZE 1024 static ssize_t gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) { const void *p, *end; void *buf; |
1da177e4c Linux-2.6.12-rc2 |
669 |
struct gss_upcall_msg *gss_msg; |
496ad9aa8 new helper: file_... |
670 |
struct rpc_pipe *pipe = RPC_I(file_inode(filp))->pipe; |
1da177e4c Linux-2.6.12-rc2 |
671 |
struct gss_cl_ctx *ctx; |
90602c7b1 sunrpc: Update gs... |
672 673 |
uid_t id; kuid_t uid; |
3b68aaeaf SUNRPC: Always ma... |
674 |
ssize_t err = -EFBIG; |
1da177e4c Linux-2.6.12-rc2 |
675 676 677 678 |
if (mlen > MSG_BUF_MAXSIZE) goto out; err = -ENOMEM; |
0f38b873a SUNRPC: Use GFP_N... |
679 |
buf = kmalloc(mlen, GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
680 681 |
if (!buf) goto out; |
1da177e4c Linux-2.6.12-rc2 |
682 683 684 685 686 |
err = -EFAULT; if (copy_from_user(buf, src, mlen)) goto err; end = (const void *)((char *)buf + mlen); |
90602c7b1 sunrpc: Update gs... |
687 |
p = simple_get_bytes(buf, end, &id, sizeof(id)); |
1da177e4c Linux-2.6.12-rc2 |
688 689 690 691 |
if (IS_ERR(p)) { err = PTR_ERR(p); goto err; } |
90602c7b1 sunrpc: Update gs... |
692 693 694 695 696 |
uid = make_kuid(&init_user_ns, id); if (!uid_valid(uid)) { err = -EINVAL; goto err; } |
1da177e4c Linux-2.6.12-rc2 |
697 698 699 700 |
err = -ENOMEM; ctx = gss_alloc_context(); if (ctx == NULL) goto err; |
3b68aaeaf SUNRPC: Always ma... |
701 702 703 |
err = -ENOENT; /* Find a matching upcall */ |
9beae4677 SUNRPC: cleanup G... |
704 |
spin_lock(&pipe->lock); |
9130b8dbc SUNRPC: allow for... |
705 |
gss_msg = __gss_find_upcall(pipe, uid, NULL); |
3b68aaeaf SUNRPC: Always ma... |
706 |
if (gss_msg == NULL) { |
9beae4677 SUNRPC: cleanup G... |
707 |
spin_unlock(&pipe->lock); |
3b68aaeaf SUNRPC: Always ma... |
708 709 710 |
goto err_put_ctx; } list_del_init(&gss_msg->list); |
9beae4677 SUNRPC: cleanup G... |
711 |
spin_unlock(&pipe->lock); |
3b68aaeaf SUNRPC: Always ma... |
712 |
|
6e84c7b66 SUNRPC: Add a dow... |
713 |
p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); |
1da177e4c Linux-2.6.12-rc2 |
714 715 |
if (IS_ERR(p)) { err = PTR_ERR(p); |
486bad2e4 sunrpc: on succes... |
716 717 |
switch (err) { case -EACCES: |
dc5ddce95 sunrpc: parse and... |
718 |
case -EKEYEXPIRED: |
486bad2e4 sunrpc: on succes... |
719 720 721 722 723 724 725 726 727 728 729 |
gss_msg->msg.errno = err; err = mlen; break; case -EFAULT: case -ENOMEM: case -EINVAL: case -ENOSYS: gss_msg->msg.errno = -EAGAIN; break; default: printk(KERN_CRIT "%s: bad return from " |
6c8530993 sunrpc: fix build... |
730 731 |
"gss_fill_context: %zd ", __func__, err); |
437b300c6 auth_gss: fix pan... |
732 |
gss_msg->msg.errno = -EIO; |
486bad2e4 sunrpc: on succes... |
733 |
} |
3b68aaeaf SUNRPC: Always ma... |
734 |
goto err_release_msg; |
1da177e4c Linux-2.6.12-rc2 |
735 |
} |
3b68aaeaf SUNRPC: Always ma... |
736 737 738 739 |
gss_msg->ctx = gss_get_ctx(ctx); err = mlen; err_release_msg: |
9beae4677 SUNRPC: cleanup G... |
740 |
spin_lock(&pipe->lock); |
3b68aaeaf SUNRPC: Always ma... |
741 |
__gss_unhash_msg(gss_msg); |
9beae4677 SUNRPC: cleanup G... |
742 |
spin_unlock(&pipe->lock); |
3b68aaeaf SUNRPC: Always ma... |
743 |
gss_release_msg(gss_msg); |
1da177e4c Linux-2.6.12-rc2 |
744 745 746 747 748 |
err_put_ctx: gss_put_ctx(ctx); err: kfree(buf); out: |
5b5e0928f lib/vsprintf.c: r... |
749 750 |
dprintk("RPC: %s returning %zd ", __func__, err); |
1da177e4c Linux-2.6.12-rc2 |
751 752 |
return err; } |
34769fc48 rpc: implement ne... |
753 |
static int gss_pipe_open(struct inode *inode, int new_version) |
cf81939d6 rpc: track number... |
754 |
{ |
2aed8b476 SUNRPC: Convert a... |
755 756 |
struct net *net = inode->i_sb->s_fs_info; struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
34769fc48 rpc: implement ne... |
757 |
int ret = 0; |
79a3f20b6 rpc: use count of... |
758 |
spin_lock(&pipe_version_lock); |
2aed8b476 SUNRPC: Convert a... |
759 |
if (sn->pipe_version < 0) { |
34769fc48 rpc: implement ne... |
760 |
/* First open of any gss pipe determines the version: */ |
2aed8b476 SUNRPC: Convert a... |
761 |
sn->pipe_version = new_version; |
79a3f20b6 rpc: use count of... |
762 763 |
rpc_wake_up(&pipe_version_rpc_waitqueue); wake_up(&pipe_version_waitqueue); |
2aed8b476 SUNRPC: Convert a... |
764 |
} else if (sn->pipe_version != new_version) { |
34769fc48 rpc: implement ne... |
765 766 767 |
/* Trying to open a pipe of a different version */ ret = -EBUSY; goto out; |
79a3f20b6 rpc: use count of... |
768 |
} |
2aed8b476 SUNRPC: Convert a... |
769 |
atomic_inc(&sn->pipe_users); |
34769fc48 rpc: implement ne... |
770 |
out: |
79a3f20b6 rpc: use count of... |
771 |
spin_unlock(&pipe_version_lock); |
34769fc48 rpc: implement ne... |
772 773 774 775 776 777 778 779 780 781 782 783 |
return ret; } static int gss_pipe_open_v0(struct inode *inode) { return gss_pipe_open(inode, 0); } static int gss_pipe_open_v1(struct inode *inode) { return gss_pipe_open(inode, 1); |
cf81939d6 rpc: track number... |
784 |
} |
1da177e4c Linux-2.6.12-rc2 |
785 786 787 |
static void gss_pipe_release(struct inode *inode) { |
2aed8b476 SUNRPC: Convert a... |
788 |
struct net *net = inode->i_sb->s_fs_info; |
9beae4677 SUNRPC: cleanup G... |
789 |
struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
6e84c7b66 SUNRPC: Add a dow... |
790 |
struct gss_upcall_msg *gss_msg; |
1da177e4c Linux-2.6.12-rc2 |
791 |
|
5a67657a2 SUNRPC: Fix race ... |
792 |
restart: |
9beae4677 SUNRPC: cleanup G... |
793 794 |
spin_lock(&pipe->lock); list_for_each_entry(gss_msg, &pipe->in_downcall, list) { |
1da177e4c Linux-2.6.12-rc2 |
795 |
|
5a67657a2 SUNRPC: Fix race ... |
796 797 |
if (!list_empty(&gss_msg->msg.list)) continue; |
1da177e4c Linux-2.6.12-rc2 |
798 |
gss_msg->msg.errno = -EPIPE; |
7ff139696 net, sunrpc: conv... |
799 |
refcount_inc(&gss_msg->count); |
1da177e4c Linux-2.6.12-rc2 |
800 |
__gss_unhash_msg(gss_msg); |
9beae4677 SUNRPC: cleanup G... |
801 |
spin_unlock(&pipe->lock); |
1da177e4c Linux-2.6.12-rc2 |
802 |
gss_release_msg(gss_msg); |
5a67657a2 SUNRPC: Fix race ... |
803 |
goto restart; |
1da177e4c Linux-2.6.12-rc2 |
804 |
} |
9beae4677 SUNRPC: cleanup G... |
805 |
spin_unlock(&pipe->lock); |
cf81939d6 rpc: track number... |
806 |
|
2aed8b476 SUNRPC: Convert a... |
807 |
put_pipe_version(net); |
1da177e4c Linux-2.6.12-rc2 |
808 809 810 811 812 813 |
} static void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) { struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); |
1da177e4c Linux-2.6.12-rc2 |
814 815 |
if (msg->errno < 0) { |
632f0d050 SUNRPC: Use __fun... |
816 817 818 |
dprintk("RPC: %s releasing msg %p ", __func__, gss_msg); |
7ff139696 net, sunrpc: conv... |
819 |
refcount_inc(&gss_msg->count); |
1da177e4c Linux-2.6.12-rc2 |
820 |
gss_unhash_msg(gss_msg); |
b03568c32 rpc: factor out w... |
821 822 |
if (msg->errno == -ETIMEDOUT) warn_gssd(); |
1da177e4c Linux-2.6.12-rc2 |
823 824 |
gss_release_msg(gss_msg); } |
1cded9d29 SUNRPC: fix refco... |
825 |
gss_release_msg(gss_msg); |
1da177e4c Linux-2.6.12-rc2 |
826 |
} |
191722843 RPCSEC_GSS: Switc... |
827 828 |
static void gss_pipe_dentry_destroy(struct dentry *dir, struct rpc_pipe_dir_object *pdo) |
ccdc28f81 SUNRPC: handle GS... |
829 |
{ |
191722843 RPCSEC_GSS: Switc... |
830 831 |
struct gss_pipe *gss_pipe = pdo->pdo_data; struct rpc_pipe *pipe = gss_pipe->pipe; |
ccdc28f81 SUNRPC: handle GS... |
832 |
|
191722843 RPCSEC_GSS: Switc... |
833 834 835 |
if (pipe->dentry != NULL) { rpc_unlink(pipe->dentry); pipe->dentry = NULL; |
6b2fddd3e RPCSEC_GSS: Fix a... |
836 |
} |
ccdc28f81 SUNRPC: handle GS... |
837 |
} |
191722843 RPCSEC_GSS: Switc... |
838 839 |
static int gss_pipe_dentry_create(struct dentry *dir, struct rpc_pipe_dir_object *pdo) |
ccdc28f81 SUNRPC: handle GS... |
840 |
{ |
191722843 RPCSEC_GSS: Switc... |
841 |
struct gss_pipe *p = pdo->pdo_data; |
6b2fddd3e RPCSEC_GSS: Fix a... |
842 |
struct dentry *dentry; |
ccdc28f81 SUNRPC: handle GS... |
843 |
|
191722843 RPCSEC_GSS: Switc... |
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 |
dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe); if (IS_ERR(dentry)) return PTR_ERR(dentry); p->pipe->dentry = dentry; return 0; } static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = { .create = gss_pipe_dentry_create, .destroy = gss_pipe_dentry_destroy, }; static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt, const char *name, const struct rpc_pipe_ops *upcall_ops) { |
191722843 RPCSEC_GSS: Switc... |
860 861 |
struct gss_pipe *p; int err = -ENOMEM; |
ccdc28f81 SUNRPC: handle GS... |
862 |
|
191722843 RPCSEC_GSS: Switc... |
863 864 |
p = kmalloc(sizeof(*p), GFP_KERNEL); if (p == NULL) |
6b2fddd3e RPCSEC_GSS: Fix a... |
865 |
goto err; |
191722843 RPCSEC_GSS: Switc... |
866 867 868 869 |
p->pipe = rpc_mkpipe_data(upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); if (IS_ERR(p->pipe)) { err = PTR_ERR(p->pipe); goto err_free_gss_pipe; |
6b2fddd3e RPCSEC_GSS: Fix a... |
870 |
} |
191722843 RPCSEC_GSS: Switc... |
871 872 |
p->name = name; p->clnt = clnt; |
414a62959 RPCSEC_GSS: Share... |
873 |
kref_init(&p->kref); |
191722843 RPCSEC_GSS: Switc... |
874 875 876 |
rpc_init_pipe_dir_object(&p->pdo, &gss_pipe_dir_object_ops, p); |
414a62959 RPCSEC_GSS: Share... |
877 |
return p; |
191722843 RPCSEC_GSS: Switc... |
878 879 |
err_free_gss_pipe: kfree(p); |
6b2fddd3e RPCSEC_GSS: Fix a... |
880 |
err: |
191722843 RPCSEC_GSS: Switc... |
881 |
return ERR_PTR(err); |
ccdc28f81 SUNRPC: handle GS... |
882 |
} |
414a62959 RPCSEC_GSS: Share... |
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 |
struct gss_alloc_pdo { struct rpc_clnt *clnt; const char *name; const struct rpc_pipe_ops *upcall_ops; }; static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data) { struct gss_pipe *gss_pipe; struct gss_alloc_pdo *args = data; if (pdo->pdo_ops != &gss_pipe_dir_object_ops) return 0; gss_pipe = container_of(pdo, struct gss_pipe, pdo); if (strcmp(gss_pipe->name, args->name) != 0) return 0; if (!kref_get_unless_zero(&gss_pipe->kref)) return 0; return 1; } static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data) { struct gss_pipe *gss_pipe; struct gss_alloc_pdo *args = data; gss_pipe = gss_pipe_alloc(args->clnt, args->name, args->upcall_ops); if (!IS_ERR(gss_pipe)) return &gss_pipe->pdo; return NULL; } static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt, const char *name, const struct rpc_pipe_ops *upcall_ops) { struct net *net = rpc_net_ns(clnt); struct rpc_pipe_dir_object *pdo; struct gss_alloc_pdo args = { .clnt = clnt, .name = name, .upcall_ops = upcall_ops, }; pdo = rpc_find_or_alloc_pipe_dir_object(net, &clnt->cl_pipedir_objects, gss_pipe_match_pdo, gss_pipe_alloc_pdo, &args); if (pdo != NULL) return container_of(pdo, struct gss_pipe, pdo); return ERR_PTR(-ENOMEM); } |
191722843 RPCSEC_GSS: Switc... |
936 |
static void __gss_pipe_free(struct gss_pipe *p) |
ccdc28f81 SUNRPC: handle GS... |
937 |
{ |
191722843 RPCSEC_GSS: Switc... |
938 939 |
struct rpc_clnt *clnt = p->clnt; struct net *net = rpc_net_ns(clnt); |
ccdc28f81 SUNRPC: handle GS... |
940 |
|
191722843 RPCSEC_GSS: Switc... |
941 942 943 944 945 |
rpc_remove_pipe_dir_object(net, &clnt->cl_pipedir_objects, &p->pdo); rpc_destroy_pipe_data(p->pipe); kfree(p); |
ccdc28f81 SUNRPC: handle GS... |
946 |
} |
414a62959 RPCSEC_GSS: Share... |
947 948 949 950 951 952 |
static void __gss_pipe_release(struct kref *kref) { struct gss_pipe *p = container_of(kref, struct gss_pipe, kref); __gss_pipe_free(p); } |
191722843 RPCSEC_GSS: Switc... |
953 |
static void gss_pipe_free(struct gss_pipe *p) |
ccdc28f81 SUNRPC: handle GS... |
954 |
{ |
191722843 RPCSEC_GSS: Switc... |
955 |
if (p != NULL) |
414a62959 RPCSEC_GSS: Share... |
956 |
kref_put(&p->kref, __gss_pipe_release); |
ccdc28f81 SUNRPC: handle GS... |
957 |
} |
cca5172a7 [NET] SUNRPC: Fix... |
958 959 |
/* * NOTE: we have the opportunity to use different |
1da177e4c Linux-2.6.12-rc2 |
960 961 |
* parameters based on the input flavor (which must be a pseudoflavor) */ |
eb6dc19d8 RPCSEC_GSS: Share... |
962 963 |
static struct gss_auth * gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
1da177e4c Linux-2.6.12-rc2 |
964 |
{ |
c21906610 SUNRPC: Replace c... |
965 |
rpc_authflavor_t flavor = args->pseudoflavor; |
1da177e4c Linux-2.6.12-rc2 |
966 |
struct gss_auth *gss_auth; |
191722843 RPCSEC_GSS: Switc... |
967 |
struct gss_pipe *gss_pipe; |
1da177e4c Linux-2.6.12-rc2 |
968 |
struct rpc_auth * auth; |
6a19275ad [PATCH] RPC: [PAT... |
969 |
int err = -ENOMEM; /* XXX? */ |
1da177e4c Linux-2.6.12-rc2 |
970 |
|
8885cb367 SUNRPC: fix print... |
971 972 |
dprintk("RPC: creating GSS authenticator for client %p ", clnt); |
1da177e4c Linux-2.6.12-rc2 |
973 974 |
if (!try_module_get(THIS_MODULE)) |
6a19275ad [PATCH] RPC: [PAT... |
975 |
return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
976 977 |
if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) goto out_dec; |
eb6dc19d8 RPCSEC_GSS: Share... |
978 |
INIT_HLIST_NODE(&gss_auth->hash); |
bd4a3eb15 RPCSEC_GSS: Clean... |
979 |
gss_auth->target_name = NULL; |
c21906610 SUNRPC: Replace c... |
980 981 |
if (args->target_name) { gss_auth->target_name = kstrdup(args->target_name, GFP_KERNEL); |
bd4a3eb15 RPCSEC_GSS: Clean... |
982 983 984 |
if (gss_auth->target_name == NULL) goto err_free; } |
1da177e4c Linux-2.6.12-rc2 |
985 |
gss_auth->client = clnt; |
e726340ac RPCSEC_GSS: Furth... |
986 |
gss_auth->net = get_net(rpc_net_ns(clnt)); |
6a19275ad [PATCH] RPC: [PAT... |
987 |
err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
988 989 |
gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); if (!gss_auth->mech) { |
9b1d75b75 SUNRPC: Don't spa... |
990 991 |
dprintk("RPC: Pseudoflavor %d not found! ", flavor); |
e726340ac RPCSEC_GSS: Furth... |
992 |
goto err_put_net; |
1da177e4c Linux-2.6.12-rc2 |
993 994 |
} gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); |
438b6fdeb [PATCH] RPC: Don'... |
995 996 |
if (gss_auth->service == 0) goto err_put_mech; |
a699d65ec SUNRPC: Don't cre... |
997 998 |
if (!gssd_running(gss_auth->net)) goto err_put_mech; |
1da177e4c Linux-2.6.12-rc2 |
999 1000 1001 |
auth = &gss_auth->rpc_auth; auth->au_cslack = GSS_CRED_SLACK >> 2; auth->au_rslack = GSS_VERF_SLACK >> 2; |
ce52914eb sunrpc: move NO_C... |
1002 |
auth->au_flags = 0; |
1da177e4c Linux-2.6.12-rc2 |
1003 1004 |
auth->au_ops = &authgss_ops; auth->au_flavor = flavor; |
65b80179f xprtrdma: No dire... |
1005 1006 |
if (gss_pseudoflavor_to_datatouch(gss_auth->mech, flavor)) auth->au_flags |= RPCAUTH_AUTH_DATATOUCH; |
1da177e4c Linux-2.6.12-rc2 |
1007 |
atomic_set(&auth->au_count, 1); |
0285ed1f1 SUNRPC: Ensure th... |
1008 |
kref_init(&gss_auth->kref); |
1da177e4c Linux-2.6.12-rc2 |
1009 |
|
191722843 RPCSEC_GSS: Switc... |
1010 1011 1012 |
err = rpcauth_init_credcache(auth); if (err) goto err_put_mech; |
34769fc48 rpc: implement ne... |
1013 1014 1015 1016 1017 1018 |
/* * Note: if we created the old pipe first, then someone who * examined the directory at the right moment might conclude * that we supported only the old pipe. So we instead create * the new pipe first. */ |
414a62959 RPCSEC_GSS: Share... |
1019 |
gss_pipe = gss_pipe_get(clnt, "gssd", &gss_upcall_ops_v1); |
191722843 RPCSEC_GSS: Switc... |
1020 1021 1022 |
if (IS_ERR(gss_pipe)) { err = PTR_ERR(gss_pipe); goto err_destroy_credcache; |
6a19275ad [PATCH] RPC: [PAT... |
1023 |
} |
191722843 RPCSEC_GSS: Switc... |
1024 |
gss_auth->gss_pipe[1] = gss_pipe; |
1da177e4c Linux-2.6.12-rc2 |
1025 |
|
414a62959 RPCSEC_GSS: Share... |
1026 |
gss_pipe = gss_pipe_get(clnt, gss_auth->mech->gm_name, |
191722843 RPCSEC_GSS: Switc... |
1027 1028 1029 |
&gss_upcall_ops_v0); if (IS_ERR(gss_pipe)) { err = PTR_ERR(gss_pipe); |
c239d83b9 SUNRPC: split SUN... |
1030 1031 |
goto err_destroy_pipe_1; } |
191722843 RPCSEC_GSS: Switc... |
1032 |
gss_auth->gss_pipe[0] = gss_pipe; |
07a2bf1da SUNRPC: Fix a mem... |
1033 |
|
eb6dc19d8 RPCSEC_GSS: Share... |
1034 |
return gss_auth; |
c239d83b9 SUNRPC: split SUN... |
1035 |
err_destroy_pipe_1: |
414a62959 RPCSEC_GSS: Share... |
1036 |
gss_pipe_free(gss_auth->gss_pipe[1]); |
191722843 RPCSEC_GSS: Switc... |
1037 1038 |
err_destroy_credcache: rpcauth_destroy_credcache(auth); |
1da177e4c Linux-2.6.12-rc2 |
1039 1040 |
err_put_mech: gss_mech_put(gss_auth->mech); |
e726340ac RPCSEC_GSS: Furth... |
1041 1042 |
err_put_net: put_net(gss_auth->net); |
1da177e4c Linux-2.6.12-rc2 |
1043 |
err_free: |
bd4a3eb15 RPCSEC_GSS: Clean... |
1044 |
kfree(gss_auth->target_name); |
1da177e4c Linux-2.6.12-rc2 |
1045 1046 1047 |
kfree(gss_auth); out_dec: module_put(THIS_MODULE); |
6a19275ad [PATCH] RPC: [PAT... |
1048 |
return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
1049 1050 1051 |
} static void |
0285ed1f1 SUNRPC: Ensure th... |
1052 1053 |
gss_free(struct gss_auth *gss_auth) { |
191722843 RPCSEC_GSS: Switc... |
1054 1055 |
gss_pipe_free(gss_auth->gss_pipe[0]); gss_pipe_free(gss_auth->gss_pipe[1]); |
0285ed1f1 SUNRPC: Ensure th... |
1056 |
gss_mech_put(gss_auth->mech); |
e726340ac RPCSEC_GSS: Furth... |
1057 |
put_net(gss_auth->net); |
bd4a3eb15 RPCSEC_GSS: Clean... |
1058 |
kfree(gss_auth->target_name); |
0285ed1f1 SUNRPC: Ensure th... |
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 |
kfree(gss_auth); module_put(THIS_MODULE); } static void gss_free_callback(struct kref *kref) { struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref); gss_free(gss_auth); } static void |
9eb2ddb48 SUNRPC: Ensure th... |
1073 1074 1075 1076 1077 1078 |
gss_put_auth(struct gss_auth *gss_auth) { kref_put(&gss_auth->kref, gss_free_callback); } static void |
1da177e4c Linux-2.6.12-rc2 |
1079 1080 |
gss_destroy(struct rpc_auth *auth) { |
191722843 RPCSEC_GSS: Switc... |
1081 1082 |
struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
1da177e4c Linux-2.6.12-rc2 |
1083 |
|
8885cb367 SUNRPC: fix print... |
1084 1085 1086 |
dprintk("RPC: destroying GSS authenticator %p flavor %d ", auth, auth->au_flavor); |
1da177e4c Linux-2.6.12-rc2 |
1087 |
|
eb6dc19d8 RPCSEC_GSS: Share... |
1088 1089 1090 1091 1092 |
if (hash_hashed(&gss_auth->hash)) { spin_lock(&gss_auth_hash_lock); hash_del(&gss_auth->hash); spin_unlock(&gss_auth_hash_lock); } |
191722843 RPCSEC_GSS: Switc... |
1093 1094 1095 1096 |
gss_pipe_free(gss_auth->gss_pipe[0]); gss_auth->gss_pipe[0] = NULL; gss_pipe_free(gss_auth->gss_pipe[1]); gss_auth->gss_pipe[1] = NULL; |
3ab9bb724 SUNRPC: Fix a mem... |
1097 |
rpcauth_destroy_credcache(auth); |
9eb2ddb48 SUNRPC: Ensure th... |
1098 |
gss_put_auth(gss_auth); |
1da177e4c Linux-2.6.12-rc2 |
1099 |
} |
a0f6ed8eb RPCSEC_GSS: fix c... |
1100 1101 1102 1103 1104 1105 1106 1107 1108 |
/* * Auths may be shared between rpc clients that were cloned from a * common client with the same xprt, if they also share the flavor and * target_name. * * The auth is looked up from the oldest parent sharing the same * cl_xprt, and the auth itself references only that common parent * (which is guaranteed to last as long as any of its descendants). */ |
eb6dc19d8 RPCSEC_GSS: Share... |
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
static struct gss_auth * gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt, struct gss_auth *new) { struct gss_auth *gss_auth; unsigned long hashval = (unsigned long)clnt; spin_lock(&gss_auth_hash_lock); hash_for_each_possible(gss_auth_hash_table, gss_auth, hash, hashval) { |
a0f6ed8eb RPCSEC_GSS: fix c... |
1122 1123 |
if (gss_auth->client != clnt) continue; |
eb6dc19d8 RPCSEC_GSS: Share... |
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 |
if (gss_auth->rpc_auth.au_flavor != args->pseudoflavor) continue; if (gss_auth->target_name != args->target_name) { if (gss_auth->target_name == NULL) continue; if (args->target_name == NULL) continue; if (strcmp(gss_auth->target_name, args->target_name)) continue; } if (!atomic_inc_not_zero(&gss_auth->rpc_auth.au_count)) continue; goto out; } if (new) hash_add(gss_auth_hash_table, &new->hash, hashval); gss_auth = new; out: spin_unlock(&gss_auth_hash_lock); return gss_auth; } static struct gss_auth * gss_create_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) { struct gss_auth *gss_auth; struct gss_auth *new; gss_auth = gss_auth_find_or_add_hashed(args, clnt, NULL); if (gss_auth != NULL) goto out; new = gss_create_new(args, clnt); if (IS_ERR(new)) return new; gss_auth = gss_auth_find_or_add_hashed(args, clnt, new); if (gss_auth != new) gss_destroy(&new->rpc_auth); out: return gss_auth; } static struct rpc_auth * gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) { struct gss_auth *gss_auth; |
ad01b2c68 SUNRPC: Make rpc_... |
1169 |
struct rpc_xprt_switch *xps = rcu_access_pointer(clnt->cl_xpi.xpi_xpswitch); |
eb6dc19d8 RPCSEC_GSS: Share... |
1170 1171 1172 1173 |
while (clnt != clnt->cl_parent) { struct rpc_clnt *parent = clnt->cl_parent; /* Find the original parent for this transport */ |
ad01b2c68 SUNRPC: Make rpc_... |
1174 |
if (rcu_access_pointer(parent->cl_xpi.xpi_xpswitch) != xps) |
eb6dc19d8 RPCSEC_GSS: Share... |
1175 1176 1177 1178 1179 1180 1181 1182 1183 |
break; clnt = parent; } gss_auth = gss_create_hashed(args, clnt); if (IS_ERR(gss_auth)) return ERR_CAST(gss_auth); return &gss_auth->rpc_auth; } |
0df7fb74f SUNRPC: Ensure RP... |
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
/* * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call * to the server with the GSS control procedure field set to * RPC_GSS_PROC_DESTROY. This should normally cause the server to release * all RPCSEC_GSS state associated with that context. */ static int gss_destroying_context(struct rpc_cred *cred) { struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
c5e6aecd0 sunrpc: fix RCU h... |
1195 |
struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); |
0df7fb74f SUNRPC: Ensure RP... |
1196 |
struct rpc_task *task; |
c5e6aecd0 sunrpc: fix RCU h... |
1197 |
if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) |
0df7fb74f SUNRPC: Ensure RP... |
1198 |
return 0; |
c5e6aecd0 sunrpc: fix RCU h... |
1199 |
ctx->gc_proc = RPC_GSS_PROC_DESTROY; |
0df7fb74f SUNRPC: Ensure RP... |
1200 1201 1202 1203 1204 |
cred->cr_ops = &gss_nullops; /* Take a reference to ensure the cred will be destroyed either * by the RPC call or by the put_rpccred() below */ get_rpccred(cred); |
080a1f148 SUNRPC: Don't att... |
1205 |
task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT); |
0df7fb74f SUNRPC: Ensure RP... |
1206 1207 1208 1209 1210 1211 1212 1213 |
if (!IS_ERR(task)) rpc_put_task(task); put_rpccred(cred); return 1; } /* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure |
1da177e4c Linux-2.6.12-rc2 |
1214 1215 1216 |
* to create a new cred or context, so they check that things have been * allocated before freeing them. */ static void |
5d28dc820 SUNRPC: Convert g... |
1217 |
gss_do_free_ctx(struct gss_cl_ctx *ctx) |
1da177e4c Linux-2.6.12-rc2 |
1218 |
{ |
632f0d050 SUNRPC: Use __fun... |
1219 1220 |
dprintk("RPC: %s ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
1221 |
|
0d8a37467 SUNRPC: Defer del... |
1222 |
gss_delete_sec_context(&ctx->gc_gss_ctx); |
1da177e4c Linux-2.6.12-rc2 |
1223 |
kfree(ctx->gc_wire_ctx.data); |
2004c726b auth_gss: fetch t... |
1224 |
kfree(ctx->gc_acceptor.data); |
1da177e4c Linux-2.6.12-rc2 |
1225 1226 1227 1228 |
kfree(ctx); } static void |
5d28dc820 SUNRPC: Convert g... |
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
gss_free_ctx_callback(struct rcu_head *head) { struct gss_cl_ctx *ctx = container_of(head, struct gss_cl_ctx, gc_rcu); gss_do_free_ctx(ctx); } static void gss_free_ctx(struct gss_cl_ctx *ctx) { call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); } static void |
31be5bf15 SUNRPC: Convert t... |
1242 |
gss_free_cred(struct gss_cred *gss_cred) |
1da177e4c Linux-2.6.12-rc2 |
1243 |
{ |
632f0d050 SUNRPC: Use __fun... |
1244 1245 |
dprintk("RPC: %s cred=%p ", __func__, gss_cred); |
31be5bf15 SUNRPC: Convert t... |
1246 1247 |
kfree(gss_cred); } |
1da177e4c Linux-2.6.12-rc2 |
1248 |
|
31be5bf15 SUNRPC: Convert t... |
1249 1250 1251 1252 1253 1254 |
static void gss_free_cred_callback(struct rcu_head *head) { struct gss_cred *gss_cred = container_of(head, struct gss_cred, gc_base.cr_rcu); gss_free_cred(gss_cred); } |
1da177e4c Linux-2.6.12-rc2 |
1255 |
|
31be5bf15 SUNRPC: Convert t... |
1256 |
static void |
6dcd3926b sunrpc: fix code ... |
1257 |
gss_destroy_nullcred(struct rpc_cred *cred) |
31be5bf15 SUNRPC: Convert t... |
1258 |
{ |
5d28dc820 SUNRPC: Convert g... |
1259 |
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
0285ed1f1 SUNRPC: Ensure th... |
1260 |
struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
c5e6aecd0 sunrpc: fix RCU h... |
1261 |
struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); |
5d28dc820 SUNRPC: Convert g... |
1262 |
|
a9b3cd7f3 rcu: convert uses... |
1263 |
RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); |
31be5bf15 SUNRPC: Convert t... |
1264 |
call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
5d28dc820 SUNRPC: Convert g... |
1265 1266 |
if (ctx) gss_put_ctx(ctx); |
9eb2ddb48 SUNRPC: Ensure th... |
1267 |
gss_put_auth(gss_auth); |
1da177e4c Linux-2.6.12-rc2 |
1268 |
} |
6dcd3926b sunrpc: fix code ... |
1269 1270 1271 1272 1273 1274 1275 1276 |
static void gss_destroy_cred(struct rpc_cred *cred) { if (gss_destroying_context(cred)) return; gss_destroy_nullcred(cred); } |
a960f8d6d sunrpc: add RPCSE... |
1277 1278 1279 1280 1281 |
static int gss_hash_cred(struct auth_cred *acred, unsigned int hashbits) { return hash_64(from_kuid(&init_user_ns, acred->uid), hashbits); } |
1da177e4c Linux-2.6.12-rc2 |
1282 1283 1284 1285 |
/* * Lookup RPCSEC_GSS cred for the current process */ static struct rpc_cred * |
8a3177604 SUNRPC: Fix a loc... |
1286 |
gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
1da177e4c Linux-2.6.12-rc2 |
1287 |
{ |
3c6e0bc8a sunrpc: plumb gfp... |
1288 |
return rpcauth_lookup_credcache(auth, acred, flags, GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
1289 1290 1291 |
} static struct rpc_cred * |
3c6e0bc8a sunrpc: plumb gfp... |
1292 |
gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags, gfp_t gfp) |
1da177e4c Linux-2.6.12-rc2 |
1293 1294 1295 1296 |
{ struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); struct gss_cred *cred = NULL; int err = -ENOMEM; |
632f0d050 SUNRPC: Use __fun... |
1297 1298 |
dprintk("RPC: %s for uid %d, flavor %d ", |
cdba321e2 sunrpc: Convert k... |
1299 1300 |
__func__, from_kuid(&init_user_ns, acred->uid), auth->au_flavor); |
1da177e4c Linux-2.6.12-rc2 |
1301 |
|
3c6e0bc8a sunrpc: plumb gfp... |
1302 |
if (!(cred = kzalloc(sizeof(*cred), gfp))) |
1da177e4c Linux-2.6.12-rc2 |
1303 |
goto out_err; |
5fe4755e2 SUNRPC: Clean up ... |
1304 |
rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops); |
1da177e4c Linux-2.6.12-rc2 |
1305 1306 1307 1308 |
/* * Note: in order to force a call to call_refresh(), we deliberately * fail to flag the credential as RPCAUTH_CRED_UPTODATE. */ |
fc432dd90 SUNRPC: Enforce a... |
1309 |
cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; |
1da177e4c Linux-2.6.12-rc2 |
1310 |
cred->gc_service = gss_auth->service; |
68c97153f SUNRPC: Clean up ... |
1311 1312 1313 |
cred->gc_principal = NULL; if (acred->machine_cred) cred->gc_principal = acred->principal; |
0285ed1f1 SUNRPC: Ensure th... |
1314 |
kref_get(&gss_auth->kref); |
1da177e4c Linux-2.6.12-rc2 |
1315 1316 1317 |
return &cred->gc_base; out_err: |
632f0d050 SUNRPC: Use __fun... |
1318 1319 |
dprintk("RPC: %s failed with error %d ", __func__, err); |
1da177e4c Linux-2.6.12-rc2 |
1320 1321 1322 1323 |
return ERR_PTR(err); } static int |
fba3bad48 SUNRPC: Move upca... |
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 |
gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) { struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); int err; do { err = gss_create_upcall(gss_auth, gss_cred); } while (err == -EAGAIN); return err; } |
a0337d1dd sunrpc: add a new... |
1335 1336 1337 |
static char * gss_stringify_acceptor(struct rpc_cred *cred) { |
c5e6aecd0 sunrpc: fix RCU h... |
1338 |
char *string = NULL; |
a0337d1dd sunrpc: add a new... |
1339 |
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
c5e6aecd0 sunrpc: fix RCU h... |
1340 |
struct gss_cl_ctx *ctx; |
b3ecba096 sunrpc: fix sleep... |
1341 |
unsigned int len; |
c5e6aecd0 sunrpc: fix RCU h... |
1342 1343 1344 1345 1346 1347 |
struct xdr_netobj *acceptor; rcu_read_lock(); ctx = rcu_dereference(gss_cred->gc_ctx); if (!ctx) goto out; |
b3ecba096 sunrpc: fix sleep... |
1348 1349 |
len = ctx->gc_acceptor.len; rcu_read_unlock(); |
a0337d1dd sunrpc: add a new... |
1350 1351 |
/* no point if there's no string */ |
b3ecba096 sunrpc: fix sleep... |
1352 1353 1354 1355 |
if (!len) return NULL; realloc: string = kmalloc(len + 1, GFP_KERNEL); |
a0337d1dd sunrpc: add a new... |
1356 |
if (!string) |
b3ecba096 sunrpc: fix sleep... |
1357 1358 1359 1360 1361 1362 1363 1364 1365 |
return NULL; rcu_read_lock(); ctx = rcu_dereference(gss_cred->gc_ctx); /* did the ctx disappear or was it replaced by one with no acceptor? */ if (!ctx || !ctx->gc_acceptor.len) { kfree(string); string = NULL; |
c5e6aecd0 sunrpc: fix RCU h... |
1366 |
goto out; |
b3ecba096 sunrpc: fix sleep... |
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 |
} acceptor = &ctx->gc_acceptor; /* * Did we find a new acceptor that's longer than the original? Allocate * a longer buffer and try again. */ if (len < acceptor->len) { len = acceptor->len; rcu_read_unlock(); kfree(string); goto realloc; } |
a0337d1dd sunrpc: add a new... |
1381 1382 1383 |
memcpy(string, acceptor->data, acceptor->len); string[acceptor->len] = '\0'; |
c5e6aecd0 sunrpc: fix RCU h... |
1384 1385 |
out: rcu_read_unlock(); |
a0337d1dd sunrpc: add a new... |
1386 1387 |
return string; } |
4de6caa27 SUNRPC new rpc_cr... |
1388 1389 1390 1391 1392 1393 1394 1395 |
/* * Returns -EACCES if GSS context is NULL or will expire within the * timeout (miliseconds) */ static int gss_key_timeout(struct rpc_cred *rc) { struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
c5e6aecd0 sunrpc: fix RCU h... |
1396 |
struct gss_cl_ctx *ctx; |
cc6a7aab5 sunrpc: avoid war... |
1397 1398 |
unsigned long timeout = jiffies + (gss_key_expire_timeo * HZ); int ret = 0; |
4de6caa27 SUNRPC new rpc_cr... |
1399 |
|
c5e6aecd0 sunrpc: fix RCU h... |
1400 1401 |
rcu_read_lock(); ctx = rcu_dereference(gss_cred->gc_ctx); |
cc6a7aab5 sunrpc: avoid war... |
1402 1403 |
if (!ctx || time_after(timeout, ctx->gc_expiry)) ret = -EACCES; |
c5e6aecd0 sunrpc: fix RCU h... |
1404 |
rcu_read_unlock(); |
cc6a7aab5 sunrpc: avoid war... |
1405 1406 |
return ret; |
4de6caa27 SUNRPC new rpc_cr... |
1407 |
} |
fba3bad48 SUNRPC: Move upca... |
1408 |
static int |
8a3177604 SUNRPC: Fix a loc... |
1409 |
gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
1da177e4c Linux-2.6.12-rc2 |
1410 1411 |
{ struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
c5e6aecd0 sunrpc: fix RCU h... |
1412 |
struct gss_cl_ctx *ctx; |
4de6caa27 SUNRPC new rpc_cr... |
1413 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
1414 |
|
cd019f751 SUNRPC: Don't cha... |
1415 |
if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
8a3177604 SUNRPC: Fix a loc... |
1416 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1417 |
/* Don't match with creds that have expired. */ |
c5e6aecd0 sunrpc: fix RCU h... |
1418 1419 1420 1421 |
rcu_read_lock(); ctx = rcu_dereference(gss_cred->gc_ctx); if (!ctx || time_after(jiffies, ctx->gc_expiry)) { rcu_read_unlock(); |
cd019f751 SUNRPC: Don't cha... |
1422 |
return 0; |
c5e6aecd0 sunrpc: fix RCU h... |
1423 1424 |
} rcu_read_unlock(); |
cd019f751 SUNRPC: Don't cha... |
1425 |
if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) |
1da177e4c Linux-2.6.12-rc2 |
1426 |
return 0; |
8a3177604 SUNRPC: Fix a loc... |
1427 |
out: |
68c97153f SUNRPC: Clean up ... |
1428 1429 1430 |
if (acred->principal != NULL) { if (gss_cred->gc_principal == NULL) return 0; |
4de6caa27 SUNRPC new rpc_cr... |
1431 1432 |
ret = strcmp(acred->principal, gss_cred->gc_principal) == 0; goto check_expire; |
68c97153f SUNRPC: Clean up ... |
1433 1434 |
} if (gss_cred->gc_principal != NULL) |
7c67db3a8 NFSv4: Reintroduc... |
1435 |
return 0; |
4de6caa27 SUNRPC new rpc_cr... |
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 |
ret = uid_eq(rc->cr_uid, acred->uid); check_expire: if (ret == 0) return ret; /* Notify acred users of GSS context expiration timeout */ if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags) && (gss_key_timeout(rc) != 0)) { /* test will now be done from generic cred */ test_and_clear_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags); /* tell NFS layer that key will expire soon */ set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); } return ret; |
1da177e4c Linux-2.6.12-rc2 |
1451 1452 1453 1454 1455 1456 |
} /* * Marshal credentials. * Maybe we should keep a cached credential for performance reasons. */ |
d8ed029d6 [SUNRPC]: trivial... |
1457 1458 |
static __be32 * gss_marshal(struct rpc_task *task, __be32 *p) |
1da177e4c Linux-2.6.12-rc2 |
1459 |
{ |
a17c2153d SUNRPC: Move the ... |
1460 1461 |
struct rpc_rqst *req = task->tk_rqstp; struct rpc_cred *cred = req->rq_cred; |
1da177e4c Linux-2.6.12-rc2 |
1462 1463 1464 |
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
d8ed029d6 [SUNRPC]: trivial... |
1465 |
__be32 *cred_len; |
1da177e4c Linux-2.6.12-rc2 |
1466 1467 1468 1469 |
u32 maj_stat = 0; struct xdr_netobj mic; struct kvec iov; struct xdr_buf verf_buf; |
632f0d050 SUNRPC: Use __fun... |
1470 1471 |
dprintk("RPC: %5u %s ", task->tk_pid, __func__); |
1da177e4c Linux-2.6.12-rc2 |
1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 |
*p++ = htonl(RPC_AUTH_GSS); cred_len = p++; spin_lock(&ctx->gc_seq_lock); req->rq_seqno = ctx->gc_seq++; spin_unlock(&ctx->gc_seq_lock); *p++ = htonl((u32) RPC_GSS_VERSION); *p++ = htonl((u32) ctx->gc_proc); *p++ = htonl((u32) req->rq_seqno); *p++ = htonl((u32) gss_cred->gc_service); p = xdr_encode_netobj(p, &ctx->gc_wire_ctx); *cred_len = htonl((p - (cred_len + 1)) << 2); /* We compute the checksum for the verifier over the xdr-encoded bytes * starting with the xid and ending at the end of the credential: */ |
a4f0835c6 SUNRPC: Eliminate... |
1489 |
iov.iov_base = xprt_skip_transport_header(req->rq_xprt, |
808012fbb [PATCH] RPC: skip... |
1490 |
req->rq_snd_buf.head[0].iov_base); |
1da177e4c Linux-2.6.12-rc2 |
1491 1492 1493 1494 1495 1496 1497 |
iov.iov_len = (u8 *)p - (u8 *)iov.iov_base; xdr_buf_from_iov(&iov, &verf_buf); /* set verifier flavor*/ *p++ = htonl(RPC_AUTH_GSS); mic.data = (u8 *)(p + 1); |
00fd6e142 RPCSEC_GSS remove... |
1498 |
maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
1da177e4c Linux-2.6.12-rc2 |
1499 |
if (maj_stat == GSS_S_CONTEXT_EXPIRED) { |
fc432dd90 SUNRPC: Enforce a... |
1500 |
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1da177e4c Linux-2.6.12-rc2 |
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 |
} else if (maj_stat != 0) { printk("gss_marshal: gss_get_mic FAILED (%d) ", maj_stat); goto out_put_ctx; } p = xdr_encode_opaque(p, NULL, mic.len); gss_put_ctx(ctx); return p; out_put_ctx: gss_put_ctx(ctx); return NULL; } |
cd019f751 SUNRPC: Don't cha... |
1513 1514 |
static int gss_renew_cred(struct rpc_task *task) { |
a17c2153d SUNRPC: Move the ... |
1515 |
struct rpc_cred *oldcred = task->tk_rqstp->rq_cred; |
cd019f751 SUNRPC: Don't cha... |
1516 1517 1518 1519 1520 1521 |
struct gss_cred *gss_cred = container_of(oldcred, struct gss_cred, gc_base); struct rpc_auth *auth = oldcred->cr_auth; struct auth_cred acred = { .uid = oldcred->cr_uid, |
68c97153f SUNRPC: Clean up ... |
1522 1523 |
.principal = gss_cred->gc_principal, .machine_cred = (gss_cred->gc_principal != NULL ? 1 : 0), |
cd019f751 SUNRPC: Don't cha... |
1524 1525 1526 1527 1528 1529 |
}; struct rpc_cred *new; new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW); if (IS_ERR(new)) return PTR_ERR(new); |
a17c2153d SUNRPC: Move the ... |
1530 |
task->tk_rqstp->rq_cred = new; |
cd019f751 SUNRPC: Don't cha... |
1531 1532 1533 |
put_rpccred(oldcred); return 0; } |
126e216a8 SUNRPC: Don't spa... |
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 |
static int gss_cred_is_negative_entry(struct rpc_cred *cred) { if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) { unsigned long now = jiffies; unsigned long begin, expire; struct gss_cred *gss_cred; gss_cred = container_of(cred, struct gss_cred, gc_base); begin = gss_cred->gc_upcall_timestamp; expire = begin + gss_expired_cred_retry_delay * HZ; if (time_in_range_open(now, begin, expire)) return 1; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1550 1551 1552 1553 1554 1555 |
/* * Refresh credentials. XXX - finish */ static int gss_refresh(struct rpc_task *task) { |
a17c2153d SUNRPC: Move the ... |
1556 |
struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
cd019f751 SUNRPC: Don't cha... |
1557 |
int ret = 0; |
126e216a8 SUNRPC: Don't spa... |
1558 1559 |
if (gss_cred_is_negative_entry(cred)) return -EKEYEXPIRED; |
cd019f751 SUNRPC: Don't cha... |
1560 1561 1562 1563 1564 |
if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) { ret = gss_renew_cred(task); if (ret < 0) goto out; |
a17c2153d SUNRPC: Move the ... |
1565 |
cred = task->tk_rqstp->rq_cred; |
cd019f751 SUNRPC: Don't cha... |
1566 |
} |
1da177e4c Linux-2.6.12-rc2 |
1567 |
|
cd019f751 SUNRPC: Don't cha... |
1568 1569 1570 1571 |
if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) ret = gss_refresh_upcall(task); out: return ret; |
1da177e4c Linux-2.6.12-rc2 |
1572 |
} |
0df7fb74f SUNRPC: Ensure RP... |
1573 1574 1575 1576 |
/* Dummy refresh routine: used only when destroying the context */ static int gss_refresh_null(struct rpc_task *task) { |
c297c8b99 SUNRPC: do not fa... |
1577 |
return 0; |
0df7fb74f SUNRPC: Ensure RP... |
1578 |
} |
d8ed029d6 [SUNRPC]: trivial... |
1579 1580 |
static __be32 * gss_validate(struct rpc_task *task, __be32 *p) |
1da177e4c Linux-2.6.12-rc2 |
1581 |
{ |
a17c2153d SUNRPC: Move the ... |
1582 |
struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1da177e4c Linux-2.6.12-rc2 |
1583 |
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
2876a3446 sunrpc: don't pas... |
1584 |
__be32 *seq = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1585 1586 1587 1588 1589 |
struct kvec iov; struct xdr_buf verf_buf; struct xdr_netobj mic; u32 flav,len; u32 maj_stat; |
35fa5f7b3 SUNRPC refactor r... |
1590 |
__be32 *ret = ERR_PTR(-EIO); |
1da177e4c Linux-2.6.12-rc2 |
1591 |
|
632f0d050 SUNRPC: Use __fun... |
1592 1593 |
dprintk("RPC: %5u %s ", task->tk_pid, __func__); |
1da177e4c Linux-2.6.12-rc2 |
1594 1595 1596 |
flav = ntohl(*p++); if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) |
cca5172a7 [NET] SUNRPC: Fix... |
1597 |
goto out_bad; |
1da177e4c Linux-2.6.12-rc2 |
1598 1599 |
if (flav != RPC_AUTH_GSS) goto out_bad; |
2876a3446 sunrpc: don't pas... |
1600 1601 1602 1603 1604 1605 |
seq = kmalloc(4, GFP_NOFS); if (!seq) goto out_bad; *seq = htonl(task->tk_rqstp->rq_seqno); iov.iov_base = seq; iov.iov_len = 4; |
1da177e4c Linux-2.6.12-rc2 |
1606 1607 1608 |
xdr_buf_from_iov(&iov, &verf_buf); mic.data = (u8 *)p; mic.len = len; |
35fa5f7b3 SUNRPC refactor r... |
1609 |
ret = ERR_PTR(-EACCES); |
00fd6e142 RPCSEC_GSS remove... |
1610 |
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
1da177e4c Linux-2.6.12-rc2 |
1611 |
if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
fc432dd90 SUNRPC: Enforce a... |
1612 |
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
0df7fb74f SUNRPC: Ensure RP... |
1613 |
if (maj_stat) { |
632f0d050 SUNRPC: Use __fun... |
1614 1615 1616 |
dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x ", task->tk_pid, __func__, maj_stat); |
1da177e4c Linux-2.6.12-rc2 |
1617 |
goto out_bad; |
0df7fb74f SUNRPC: Ensure RP... |
1618 |
} |
24b2605be RPCSEC_GSS: clean... |
1619 1620 |
/* We leave it to unwrap to calculate au_rslack. For now we just * calculate the length of the verifier: */ |
1be27f366 SUNRPC: Remove th... |
1621 |
cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; |
1da177e4c Linux-2.6.12-rc2 |
1622 |
gss_put_ctx(ctx); |
632f0d050 SUNRPC: Use __fun... |
1623 1624 1625 |
dprintk("RPC: %5u %s: gss_verify_mic succeeded. ", task->tk_pid, __func__); |
2876a3446 sunrpc: don't pas... |
1626 |
kfree(seq); |
1da177e4c Linux-2.6.12-rc2 |
1627 1628 1629 |
return p + XDR_QUADLEN(len); out_bad: gss_put_ctx(ctx); |
35fa5f7b3 SUNRPC refactor r... |
1630 1631 1632 |
dprintk("RPC: %5u %s failed ret %ld. ", task->tk_pid, __func__, PTR_ERR(ret)); |
2876a3446 sunrpc: don't pas... |
1633 |
kfree(seq); |
35fa5f7b3 SUNRPC refactor r... |
1634 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1635 |
} |
9f06c719f SUNRPC: New xdr_s... |
1636 1637 1638 1639 1640 1641 1642 1643 |
static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj) { struct xdr_stream xdr; xdr_init_encode(&xdr, &rqstp->rq_snd_buf, p); encode(rqstp, &xdr, obj); } |
1da177e4c Linux-2.6.12-rc2 |
1644 1645 |
static inline int gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, |
9f06c719f SUNRPC: New xdr_s... |
1646 1647 |
kxdreproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj) |
1da177e4c Linux-2.6.12-rc2 |
1648 1649 1650 |
{ struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; struct xdr_buf integ_buf; |
d8ed029d6 [SUNRPC]: trivial... |
1651 |
__be32 *integ_len = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1652 |
struct xdr_netobj mic; |
d8ed029d6 [SUNRPC]: trivial... |
1653 1654 |
u32 offset; __be32 *q; |
1da177e4c Linux-2.6.12-rc2 |
1655 1656 1657 1658 1659 1660 1661 |
struct kvec *iov; u32 maj_stat = 0; int status = -EIO; integ_len = p++; offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; *p++ = htonl(rqstp->rq_seqno); |
9f06c719f SUNRPC: New xdr_s... |
1662 |
gss_wrap_req_encode(encode, rqstp, p, obj); |
1da177e4c Linux-2.6.12-rc2 |
1663 1664 1665 1666 1667 1668 1669 |
if (xdr_buf_subsegment(snd_buf, &integ_buf, offset, snd_buf->len - offset)) return status; *integ_len = htonl(integ_buf.len); /* guess whether we're in the head or the tail: */ |
cca5172a7 [NET] SUNRPC: Fix... |
1670 |
if (snd_buf->page_len || snd_buf->tail[0].iov_len) |
1da177e4c Linux-2.6.12-rc2 |
1671 1672 1673 1674 1675 |
iov = snd_buf->tail; else iov = snd_buf->head; p = iov->iov_base + iov->iov_len; mic.data = (u8 *)(p + 1); |
00fd6e142 RPCSEC_GSS remove... |
1676 |
maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); |
1da177e4c Linux-2.6.12-rc2 |
1677 1678 |
status = -EIO; /* XXX? */ if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
fc432dd90 SUNRPC: Enforce a... |
1679 |
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1da177e4c Linux-2.6.12-rc2 |
1680 1681 1682 1683 1684 1685 1686 1687 1688 |
else if (maj_stat) return status; q = xdr_encode_opaque(p, NULL, mic.len); offset = (u8 *)q - (u8 *)p; iov->iov_len += offset; snd_buf->len += offset; return 0; } |
2d2da60c6 RPCSEC_GSS: clien... |
1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 |
static void priv_release_snd_buf(struct rpc_rqst *rqstp) { int i; for (i=0; i < rqstp->rq_enc_pages_num; i++) __free_page(rqstp->rq_enc_pages[i]); kfree(rqstp->rq_enc_pages); } static int alloc_enc_pages(struct rpc_rqst *rqstp) { struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; int first, last, i; if (snd_buf->page_len == 0) { rqstp->rq_enc_pages_num = 0; return 0; } |
09cbfeaf1 mm, fs: get rid o... |
1709 1710 |
first = snd_buf->page_base >> PAGE_SHIFT; last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_SHIFT; |
2d2da60c6 RPCSEC_GSS: clien... |
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 |
rqstp->rq_enc_pages_num = last - first + 1 + 1; rqstp->rq_enc_pages = kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *), GFP_NOFS); if (!rqstp->rq_enc_pages) goto out; for (i=0; i < rqstp->rq_enc_pages_num; i++) { rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS); if (rqstp->rq_enc_pages[i] == NULL) goto out_free; } rqstp->rq_release_snd_buf = priv_release_snd_buf; return 0; out_free: |
cdead7cf1 SUNRPC: Fix a pot... |
1725 1726 |
rqstp->rq_enc_pages_num = i; priv_release_snd_buf(rqstp); |
2d2da60c6 RPCSEC_GSS: clien... |
1727 1728 1729 1730 1731 1732 |
out: return -EAGAIN; } static inline int gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, |
9f06c719f SUNRPC: New xdr_s... |
1733 1734 |
kxdreproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj) |
2d2da60c6 RPCSEC_GSS: clien... |
1735 1736 1737 1738 1739 |
{ struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; u32 offset; u32 maj_stat; int status; |
d8ed029d6 [SUNRPC]: trivial... |
1740 |
__be32 *opaque_len; |
2d2da60c6 RPCSEC_GSS: clien... |
1741 1742 1743 1744 1745 1746 1747 1748 1749 |
struct page **inpages; int first; int pad; struct kvec *iov; char *tmp; opaque_len = p++; offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; *p++ = htonl(rqstp->rq_seqno); |
9f06c719f SUNRPC: New xdr_s... |
1750 |
gss_wrap_req_encode(encode, rqstp, p, obj); |
2d2da60c6 RPCSEC_GSS: clien... |
1751 1752 1753 1754 |
status = alloc_enc_pages(rqstp); if (status) return status; |
09cbfeaf1 mm, fs: get rid o... |
1755 |
first = snd_buf->page_base >> PAGE_SHIFT; |
2d2da60c6 RPCSEC_GSS: clien... |
1756 1757 |
inpages = snd_buf->pages + first; snd_buf->pages = rqstp->rq_enc_pages; |
09cbfeaf1 mm, fs: get rid o... |
1758 |
snd_buf->page_base -= first << PAGE_SHIFT; |
7561042fb gss_krb5: Added a... |
1759 1760 1761 1762 1763 1764 1765 1766 |
/* * Give the tail its own page, in case we need extra space in the * head when wrapping: * * call_allocate() allocates twice the slack space required * by the authentication flavor to rq_callsize. * For GSS, slack is GSS_CRED_SLACK. */ |
2d2da60c6 RPCSEC_GSS: clien... |
1767 1768 1769 1770 1771 |
if (snd_buf->page_len || snd_buf->tail[0].iov_len) { tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]); memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len); snd_buf->tail[0].iov_base = tmp; } |
00fd6e142 RPCSEC_GSS remove... |
1772 |
maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages); |
7561042fb gss_krb5: Added a... |
1773 |
/* slack space should prevent this ever happening: */ |
2d2da60c6 RPCSEC_GSS: clien... |
1774 |
BUG_ON(snd_buf->len > snd_buf->buflen); |
cca5172a7 [NET] SUNRPC: Fix... |
1775 |
status = -EIO; |
2d2da60c6 RPCSEC_GSS: clien... |
1776 1777 1778 |
/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was * done anyway, so it's safe to put the request on the wire: */ if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
fc432dd90 SUNRPC: Enforce a... |
1779 |
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
2d2da60c6 RPCSEC_GSS: clien... |
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 |
else if (maj_stat) return status; *opaque_len = htonl(snd_buf->len - offset); /* guess whether we're in the head or the tail: */ if (snd_buf->page_len || snd_buf->tail[0].iov_len) iov = snd_buf->tail; else iov = snd_buf->head; p = iov->iov_base + iov->iov_len; pad = 3 - ((snd_buf->len - offset - 1) & 3); memset(p, 0, pad); iov->iov_len += pad; snd_buf->len += pad; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1797 1798 |
static int gss_wrap_req(struct rpc_task *task, |
9f06c719f SUNRPC: New xdr_s... |
1799 |
kxdreproc_t encode, void *rqstp, __be32 *p, void *obj) |
1da177e4c Linux-2.6.12-rc2 |
1800 |
{ |
a17c2153d SUNRPC: Move the ... |
1801 |
struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1da177e4c Linux-2.6.12-rc2 |
1802 1803 1804 1805 |
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); int status = -EIO; |
632f0d050 SUNRPC: Use __fun... |
1806 1807 |
dprintk("RPC: %5u %s ", task->tk_pid, __func__); |
1da177e4c Linux-2.6.12-rc2 |
1808 1809 1810 1811 |
if (ctx->gc_proc != RPC_GSS_PROC_DATA) { /* The spec seems a little ambiguous here, but I think that not * wrapping context destruction requests makes the most sense. */ |
9f06c719f SUNRPC: New xdr_s... |
1812 1813 |
gss_wrap_req_encode(encode, rqstp, p, obj); status = 0; |
1da177e4c Linux-2.6.12-rc2 |
1814 1815 1816 |
goto out; } switch (gss_cred->gc_service) { |
89f0e4fea sunrpc: Reduce sw... |
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 |
case RPC_GSS_SVC_NONE: gss_wrap_req_encode(encode, rqstp, p, obj); status = 0; break; case RPC_GSS_SVC_INTEGRITY: status = gss_wrap_req_integ(cred, ctx, encode, rqstp, p, obj); break; case RPC_GSS_SVC_PRIVACY: status = gss_wrap_req_priv(cred, ctx, encode, rqstp, p, obj); break; |
1da177e4c Linux-2.6.12-rc2 |
1827 1828 1829 |
} out: gss_put_ctx(ctx); |
632f0d050 SUNRPC: Use __fun... |
1830 1831 |
dprintk("RPC: %5u %s returning %d ", task->tk_pid, __func__, status); |
1da177e4c Linux-2.6.12-rc2 |
1832 1833 1834 1835 1836 |
return status; } static inline int gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, |
d8ed029d6 [SUNRPC]: trivial... |
1837 |
struct rpc_rqst *rqstp, __be32 **p) |
1da177e4c Linux-2.6.12-rc2 |
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 |
{ struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; struct xdr_buf integ_buf; struct xdr_netobj mic; u32 data_offset, mic_offset; u32 integ_len; u32 maj_stat; int status = -EIO; integ_len = ntohl(*(*p)++); if (integ_len & 3) return status; data_offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; mic_offset = integ_len + data_offset; if (mic_offset > rcv_buf->len) return status; if (ntohl(*(*p)++) != rqstp->rq_seqno) return status; if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, mic_offset - data_offset)) return status; if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset)) return status; |
00fd6e142 RPCSEC_GSS remove... |
1863 |
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); |
1da177e4c Linux-2.6.12-rc2 |
1864 |
if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
fc432dd90 SUNRPC: Enforce a... |
1865 |
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1da177e4c Linux-2.6.12-rc2 |
1866 1867 1868 1869 |
if (maj_stat != GSS_S_COMPLETE) return status; return 0; } |
2d2da60c6 RPCSEC_GSS: clien... |
1870 1871 |
static inline int gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, |
d8ed029d6 [SUNRPC]: trivial... |
1872 |
struct rpc_rqst *rqstp, __be32 **p) |
2d2da60c6 RPCSEC_GSS: clien... |
1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 |
{ struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; u32 offset; u32 opaque_len; u32 maj_stat; int status = -EIO; opaque_len = ntohl(*(*p)++); offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; if (offset + opaque_len > rcv_buf->len) return status; /* remove padding: */ rcv_buf->len = offset + opaque_len; |
00fd6e142 RPCSEC_GSS remove... |
1886 |
maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); |
2d2da60c6 RPCSEC_GSS: clien... |
1887 |
if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
fc432dd90 SUNRPC: Enforce a... |
1888 |
clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
2d2da60c6 RPCSEC_GSS: clien... |
1889 1890 1891 1892 1893 1894 1895 |
if (maj_stat != GSS_S_COMPLETE) return status; if (ntohl(*(*p)++) != rqstp->rq_seqno) return status; return 0; } |
bf2695516 SUNRPC: New xdr_s... |
1896 1897 1898 1899 1900 1901 1902 1903 1904 |
static int gss_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp, __be32 *p, void *obj) { struct xdr_stream xdr; xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); return decode(rqstp, &xdr, obj); } |
2d2da60c6 RPCSEC_GSS: clien... |
1905 |
|
1da177e4c Linux-2.6.12-rc2 |
1906 1907 |
static int gss_unwrap_resp(struct rpc_task *task, |
bf2695516 SUNRPC: New xdr_s... |
1908 |
kxdrdproc_t decode, void *rqstp, __be32 *p, void *obj) |
1da177e4c Linux-2.6.12-rc2 |
1909 |
{ |
a17c2153d SUNRPC: Move the ... |
1910 |
struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1da177e4c Linux-2.6.12-rc2 |
1911 1912 1913 |
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
d8ed029d6 [SUNRPC]: trivial... |
1914 |
__be32 *savedp = p; |
2d2da60c6 RPCSEC_GSS: clien... |
1915 1916 |
struct kvec *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head; int savedlen = head->iov_len; |
1da177e4c Linux-2.6.12-rc2 |
1917 1918 1919 1920 1921 |
int status = -EIO; if (ctx->gc_proc != RPC_GSS_PROC_DATA) goto out_decode; switch (gss_cred->gc_service) { |
89f0e4fea sunrpc: Reduce sw... |
1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 |
case RPC_GSS_SVC_NONE: break; case RPC_GSS_SVC_INTEGRITY: status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p); if (status) goto out; break; case RPC_GSS_SVC_PRIVACY: status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p); if (status) goto out; break; |
1da177e4c Linux-2.6.12-rc2 |
1934 |
} |
24b2605be RPCSEC_GSS: clean... |
1935 |
/* take into account extra slack for integrity and privacy cases: */ |
1be27f366 SUNRPC: Remove th... |
1936 |
cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp) |
2d2da60c6 RPCSEC_GSS: clien... |
1937 |
+ (savedlen - head->iov_len); |
1da177e4c Linux-2.6.12-rc2 |
1938 |
out_decode: |
bf2695516 SUNRPC: New xdr_s... |
1939 |
status = gss_unwrap_req_decode(decode, rqstp, p, obj); |
1da177e4c Linux-2.6.12-rc2 |
1940 1941 |
out: gss_put_ctx(ctx); |
632f0d050 SUNRPC: Use __fun... |
1942 1943 1944 |
dprintk("RPC: %5u %s returning %d ", task->tk_pid, __func__, status); |
1da177e4c Linux-2.6.12-rc2 |
1945 1946 |
return status; } |
cca5172a7 [NET] SUNRPC: Fix... |
1947 |
|
f1c0a8615 SUNRPC: Mark auth... |
1948 |
static const struct rpc_authops authgss_ops = { |
1da177e4c Linux-2.6.12-rc2 |
1949 1950 |
.owner = THIS_MODULE, .au_flavor = RPC_AUTH_GSS, |
1da177e4c Linux-2.6.12-rc2 |
1951 |
.au_name = "RPCSEC_GSS", |
1da177e4c Linux-2.6.12-rc2 |
1952 1953 |
.create = gss_create, .destroy = gss_destroy, |
a960f8d6d sunrpc: add RPCSE... |
1954 |
.hash_cred = gss_hash_cred, |
1da177e4c Linux-2.6.12-rc2 |
1955 |
.lookup_cred = gss_lookup_cred, |
80df9d202 SUNRPC: subscribe... |
1956 |
.crcreate = gss_create_cred, |
6a1a1e34d SUNRPC: Add rpcau... |
1957 |
.list_pseudoflavors = gss_mech_list_pseudoflavors, |
9568c5e9a SUNRPC: Introduce... |
1958 |
.info2flavor = gss_mech_info2flavor, |
a77c806fb SUNRPC: Refactor ... |
1959 |
.flavor2info = gss_mech_flavor2info, |
1da177e4c Linux-2.6.12-rc2 |
1960 |
}; |
f1c0a8615 SUNRPC: Mark auth... |
1961 |
static const struct rpc_credops gss_credops = { |
a0337d1dd sunrpc: add a new... |
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 |
.cr_name = "AUTH_GSS", .crdestroy = gss_destroy_cred, .cr_init = gss_cred_init, .crbind = rpcauth_generic_bind_cred, .crmatch = gss_match, .crmarshal = gss_marshal, .crrefresh = gss_refresh, .crvalidate = gss_validate, .crwrap_req = gss_wrap_req, .crunwrap_resp = gss_unwrap_resp, .crkey_timeout = gss_key_timeout, .crstringify_acceptor = gss_stringify_acceptor, |
1da177e4c Linux-2.6.12-rc2 |
1974 |
}; |
0df7fb74f SUNRPC: Ensure RP... |
1975 |
static const struct rpc_credops gss_nullops = { |
a0337d1dd sunrpc: add a new... |
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 |
.cr_name = "AUTH_GSS", .crdestroy = gss_destroy_nullcred, .crbind = rpcauth_generic_bind_cred, .crmatch = gss_match, .crmarshal = gss_marshal, .crrefresh = gss_refresh_null, .crvalidate = gss_validate, .crwrap_req = gss_wrap_req, .crunwrap_resp = gss_unwrap_resp, .crstringify_acceptor = gss_stringify_acceptor, |
0df7fb74f SUNRPC: Ensure RP... |
1986 |
}; |
b693ba4a3 SUNRPC: Constify ... |
1987 |
static const struct rpc_pipe_ops gss_upcall_ops_v0 = { |
c1225158a SUNRPC/NFS: make ... |
1988 |
.upcall = rpc_pipe_generic_upcall, |
34769fc48 rpc: implement ne... |
1989 1990 1991 1992 1993 |
.downcall = gss_pipe_downcall, .destroy_msg = gss_pipe_destroy_msg, .open_pipe = gss_pipe_open_v0, .release_pipe = gss_pipe_release, }; |
b693ba4a3 SUNRPC: Constify ... |
1994 |
static const struct rpc_pipe_ops gss_upcall_ops_v1 = { |
c1225158a SUNRPC/NFS: make ... |
1995 |
.upcall = rpc_pipe_generic_upcall, |
1da177e4c Linux-2.6.12-rc2 |
1996 1997 |
.downcall = gss_pipe_downcall, .destroy_msg = gss_pipe_destroy_msg, |
34769fc48 rpc: implement ne... |
1998 |
.open_pipe = gss_pipe_open_v1, |
1da177e4c Linux-2.6.12-rc2 |
1999 2000 |
.release_pipe = gss_pipe_release, }; |
a1db410d0 SUNRPC: create GS... |
2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 |
static __net_init int rpcsec_gss_init_net(struct net *net) { return gss_svc_init_net(net); } static __net_exit void rpcsec_gss_exit_net(struct net *net) { gss_svc_shutdown_net(net); } static struct pernet_operations rpcsec_gss_net_ops = { .init = rpcsec_gss_init_net, .exit = rpcsec_gss_exit_net, }; |
1da177e4c Linux-2.6.12-rc2 |
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 |
/* * Initialize RPCSEC_GSS module */ static int __init init_rpcsec_gss(void) { int err = 0; err = rpcauth_register(&authgss_ops); if (err) goto out; err = gss_svc_init(); if (err) goto out_unregister; |
a1db410d0 SUNRPC: create GS... |
2028 2029 2030 |
err = register_pernet_subsys(&rpcsec_gss_net_ops); if (err) goto out_svc_exit; |
79a3f20b6 rpc: use count of... |
2031 |
rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); |
1da177e4c Linux-2.6.12-rc2 |
2032 |
return 0; |
a1db410d0 SUNRPC: create GS... |
2033 2034 |
out_svc_exit: gss_svc_shutdown(); |
1da177e4c Linux-2.6.12-rc2 |
2035 2036 2037 2038 2039 2040 2041 2042 |
out_unregister: rpcauth_unregister(&authgss_ops); out: return err; } static void __exit exit_rpcsec_gss(void) { |
a1db410d0 SUNRPC: create GS... |
2043 |
unregister_pernet_subsys(&rpcsec_gss_net_ops); |
1da177e4c Linux-2.6.12-rc2 |
2044 2045 |
gss_svc_shutdown(); rpcauth_unregister(&authgss_ops); |
bf12691d8 sunrpc/auth_gss: ... |
2046 |
rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
1da177e4c Linux-2.6.12-rc2 |
2047 |
} |
71afa85e7 SUNRPC: Missing m... |
2048 |
MODULE_ALIAS("rpc-auth-6"); |
1da177e4c Linux-2.6.12-rc2 |
2049 |
MODULE_LICENSE("GPL"); |
126e216a8 SUNRPC: Don't spa... |
2050 2051 2052 2053 2054 |
module_param_named(expired_cred_retry_delay, gss_expired_cred_retry_delay, uint, 0644); MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " "the RPC engine retries an expired credential"); |
4de6caa27 SUNRPC new rpc_cr... |
2055 2056 2057 2058 2059 2060 |
module_param_named(key_expire_timeo, gss_key_expire_timeo, uint, 0644); MODULE_PARM_DESC(key_expire_timeo, "Time (in seconds) at the end of a " "credential keys lifetime where the NFS layer cleans up " "prior to key expiration"); |
1da177e4c Linux-2.6.12-rc2 |
2061 2062 |
module_init(init_rpcsec_gss) module_exit(exit_rpcsec_gss) |