auth_gss.c revision adeb8133dd57f380e70a389a89a2ea3ae227f9e2
1/* 2 * linux/net/sunrpc/auth_gss/auth_gss.c 3 * 4 * RPCSEC_GSS client authentication. 5 * 6 * Copyright (c) 2000 The Regents of the University of Michigan. 7 * All rights reserved. 8 * 9 * Dug Song <dugsong@monkey.org> 10 * Andy Adamson <andros@umich.edu> 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 32 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * $Id$ 38 */ 39 40 41#include <linux/module.h> 42#include <linux/init.h> 43#include <linux/types.h> 44#include <linux/slab.h> 45#include <linux/sched.h> 46#include <linux/pagemap.h> 47#include <linux/sunrpc/clnt.h> 48#include <linux/sunrpc/auth.h> 49#include <linux/sunrpc/auth_gss.h> 50#include <linux/sunrpc/svcauth_gss.h> 51#include <linux/sunrpc/gss_err.h> 52#include <linux/workqueue.h> 53#include <linux/sunrpc/rpc_pipe_fs.h> 54#include <linux/sunrpc/gss_api.h> 55#include <asm/uaccess.h> 56 57static struct rpc_authops authgss_ops; 58 59static struct rpc_credops gss_credops; 60 61#ifdef RPC_DEBUG 62# define RPCDBG_FACILITY RPCDBG_AUTH 63#endif 64 65#define NFS_NGROUPS 16 66 67#define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */ 68#define GSS_CRED_SLACK 1024 /* XXX: unused */ 69/* length of a krb5 verifier (48), plus data added before arguments when 70 * using integrity (two 4-byte integers): */ 71#define GSS_VERF_SLACK 100 72 73/* XXX this define must match the gssd define 74* as it is passed to gssd to signal the use of 75* machine creds should be part of the shared rpc interface */ 76 77#define CA_RUN_AS_MACHINE 0x00000200 78 79/* dump the buffer in `emacs-hexl' style */ 80#define isprint(c) ((c > 0x1f) && (c < 0x7f)) 81 82static DEFINE_RWLOCK(gss_ctx_lock); 83 84struct gss_auth { 85 struct rpc_auth rpc_auth; 86 struct gss_api_mech *mech; 87 enum rpc_gss_svc service; 88 struct list_head upcalls; 89 struct rpc_clnt *client; 90 struct dentry *dentry; 91 spinlock_t lock; 92}; 93 94static void gss_destroy_ctx(struct gss_cl_ctx *); 95static struct rpc_pipe_ops gss_upcall_ops; 96 97static inline struct gss_cl_ctx * 98gss_get_ctx(struct gss_cl_ctx *ctx) 99{ 100 atomic_inc(&ctx->count); 101 return ctx; 102} 103 104static inline void 105gss_put_ctx(struct gss_cl_ctx *ctx) 106{ 107 if (atomic_dec_and_test(&ctx->count)) 108 gss_destroy_ctx(ctx); 109} 110 111static void 112gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) 113{ 114 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 115 struct gss_cl_ctx *old; 116 write_lock(&gss_ctx_lock); 117 old = gss_cred->gc_ctx; 118 gss_cred->gc_ctx = ctx; 119 cred->cr_flags |= RPCAUTH_CRED_UPTODATE; 120 cred->cr_flags &= ~RPCAUTH_CRED_NEW; 121 write_unlock(&gss_ctx_lock); 122 if (old) 123 gss_put_ctx(old); 124} 125 126static int 127gss_cred_is_uptodate_ctx(struct rpc_cred *cred) 128{ 129 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 130 int res = 0; 131 132 read_lock(&gss_ctx_lock); 133 if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx) 134 res = 1; 135 read_unlock(&gss_ctx_lock); 136 return res; 137} 138 139static const void * 140simple_get_bytes(const void *p, const void *end, void *res, size_t len) 141{ 142 const void *q = (const void *)((const char *)p + len); 143 if (unlikely(q > end || q < p)) 144 return ERR_PTR(-EFAULT); 145 memcpy(res, p, len); 146 return q; 147} 148 149static inline const void * 150simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest) 151{ 152 const void *q; 153 unsigned int len; 154 155 p = simple_get_bytes(p, end, &len, sizeof(len)); 156 if (IS_ERR(p)) 157 return p; 158 q = (const void *)((const char *)p + len); 159 if (unlikely(q > end || q < p)) 160 return ERR_PTR(-EFAULT); 161 dest->data = kmemdup(p, len, GFP_KERNEL); 162 if (unlikely(dest->data == NULL)) 163 return ERR_PTR(-ENOMEM); 164 dest->len = len; 165 return q; 166} 167 168static struct gss_cl_ctx * 169gss_cred_get_ctx(struct rpc_cred *cred) 170{ 171 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 172 struct gss_cl_ctx *ctx = NULL; 173 174 read_lock(&gss_ctx_lock); 175 if (gss_cred->gc_ctx) 176 ctx = gss_get_ctx(gss_cred->gc_ctx); 177 read_unlock(&gss_ctx_lock); 178 return ctx; 179} 180 181static struct gss_cl_ctx * 182gss_alloc_context(void) 183{ 184 struct gss_cl_ctx *ctx; 185 186 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 187 if (ctx != NULL) { 188 ctx->gc_proc = RPC_GSS_PROC_DATA; 189 ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */ 190 spin_lock_init(&ctx->gc_seq_lock); 191 atomic_set(&ctx->count,1); 192 } 193 return ctx; 194} 195 196#define GSSD_MIN_TIMEOUT (60 * 60) 197static const void * 198gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm) 199{ 200 const void *q; 201 unsigned int seclen; 202 unsigned int timeout; 203 u32 window_size; 204 int ret; 205 206 /* First unsigned int gives the lifetime (in seconds) of the cred */ 207 p = simple_get_bytes(p, end, &timeout, sizeof(timeout)); 208 if (IS_ERR(p)) 209 goto err; 210 if (timeout == 0) 211 timeout = GSSD_MIN_TIMEOUT; 212 ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4; 213 /* Sequence number window. Determines the maximum number of simultaneous requests */ 214 p = simple_get_bytes(p, end, &window_size, sizeof(window_size)); 215 if (IS_ERR(p)) 216 goto err; 217 ctx->gc_win = window_size; 218 /* gssd signals an error by passing ctx->gc_win = 0: */ 219 if (ctx->gc_win == 0) { 220 /* in which case, p points to an error code which we ignore */ 221 p = ERR_PTR(-EACCES); 222 goto err; 223 } 224 /* copy the opaque wire context */ 225 p = simple_get_netobj(p, end, &ctx->gc_wire_ctx); 226 if (IS_ERR(p)) 227 goto err; 228 /* import the opaque security context */ 229 p = simple_get_bytes(p, end, &seclen, sizeof(seclen)); 230 if (IS_ERR(p)) 231 goto err; 232 q = (const void *)((const char *)p + seclen); 233 if (unlikely(q > end || q < p)) { 234 p = ERR_PTR(-EFAULT); 235 goto err; 236 } 237 ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx); 238 if (ret < 0) { 239 p = ERR_PTR(ret); 240 goto err; 241 } 242 return q; 243err: 244 dprintk("RPC: gss_fill_context returning %ld\n", -PTR_ERR(p)); 245 return p; 246} 247 248 249struct gss_upcall_msg { 250 atomic_t count; 251 uid_t uid; 252 struct rpc_pipe_msg msg; 253 struct list_head list; 254 struct gss_auth *auth; 255 struct rpc_wait_queue rpc_waitqueue; 256 wait_queue_head_t waitqueue; 257 struct gss_cl_ctx *ctx; 258}; 259 260static void 261gss_release_msg(struct gss_upcall_msg *gss_msg) 262{ 263 if (!atomic_dec_and_test(&gss_msg->count)) 264 return; 265 BUG_ON(!list_empty(&gss_msg->list)); 266 if (gss_msg->ctx != NULL) 267 gss_put_ctx(gss_msg->ctx); 268 kfree(gss_msg); 269} 270 271static struct gss_upcall_msg * 272__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid) 273{ 274 struct gss_upcall_msg *pos; 275 list_for_each_entry(pos, &gss_auth->upcalls, list) { 276 if (pos->uid != uid) 277 continue; 278 atomic_inc(&pos->count); 279 dprintk("RPC: gss_find_upcall found msg %p\n", pos); 280 return pos; 281 } 282 dprintk("RPC: gss_find_upcall found nothing\n"); 283 return NULL; 284} 285 286/* Try to add a upcall to the pipefs queue. 287 * If an upcall owned by our uid already exists, then we return a reference 288 * to that upcall instead of adding the new upcall. 289 */ 290static inline struct gss_upcall_msg * 291gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg) 292{ 293 struct gss_upcall_msg *old; 294 295 spin_lock(&gss_auth->lock); 296 old = __gss_find_upcall(gss_auth, gss_msg->uid); 297 if (old == NULL) { 298 atomic_inc(&gss_msg->count); 299 list_add(&gss_msg->list, &gss_auth->upcalls); 300 } else 301 gss_msg = old; 302 spin_unlock(&gss_auth->lock); 303 return gss_msg; 304} 305 306static void 307__gss_unhash_msg(struct gss_upcall_msg *gss_msg) 308{ 309 if (list_empty(&gss_msg->list)) 310 return; 311 list_del_init(&gss_msg->list); 312 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); 313 wake_up_all(&gss_msg->waitqueue); 314 atomic_dec(&gss_msg->count); 315} 316 317static void 318gss_unhash_msg(struct gss_upcall_msg *gss_msg) 319{ 320 struct gss_auth *gss_auth = gss_msg->auth; 321 322 spin_lock(&gss_auth->lock); 323 __gss_unhash_msg(gss_msg); 324 spin_unlock(&gss_auth->lock); 325} 326 327static void 328gss_upcall_callback(struct rpc_task *task) 329{ 330 struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, 331 struct gss_cred, gc_base); 332 struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; 333 334 BUG_ON(gss_msg == NULL); 335 if (gss_msg->ctx) 336 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx)); 337 else 338 task->tk_status = gss_msg->msg.errno; 339 spin_lock(&gss_msg->auth->lock); 340 gss_cred->gc_upcall = NULL; 341 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); 342 spin_unlock(&gss_msg->auth->lock); 343 gss_release_msg(gss_msg); 344} 345 346static inline struct gss_upcall_msg * 347gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid) 348{ 349 struct gss_upcall_msg *gss_msg; 350 351 gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL); 352 if (gss_msg != NULL) { 353 INIT_LIST_HEAD(&gss_msg->list); 354 rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); 355 init_waitqueue_head(&gss_msg->waitqueue); 356 atomic_set(&gss_msg->count, 1); 357 gss_msg->msg.data = &gss_msg->uid; 358 gss_msg->msg.len = sizeof(gss_msg->uid); 359 gss_msg->uid = uid; 360 gss_msg->auth = gss_auth; 361 } 362 return gss_msg; 363} 364 365static struct gss_upcall_msg * 366gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred) 367{ 368 struct gss_upcall_msg *gss_new, *gss_msg; 369 370 gss_new = gss_alloc_msg(gss_auth, cred->cr_uid); 371 if (gss_new == NULL) 372 return ERR_PTR(-ENOMEM); 373 gss_msg = gss_add_msg(gss_auth, gss_new); 374 if (gss_msg == gss_new) { 375 int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg); 376 if (res) { 377 gss_unhash_msg(gss_new); 378 gss_msg = ERR_PTR(res); 379 } 380 } else 381 gss_release_msg(gss_new); 382 return gss_msg; 383} 384 385static inline int 386gss_refresh_upcall(struct rpc_task *task) 387{ 388 struct rpc_cred *cred = task->tk_msg.rpc_cred; 389 struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth, 390 struct gss_auth, rpc_auth); 391 struct gss_cred *gss_cred = container_of(cred, 392 struct gss_cred, gc_base); 393 struct gss_upcall_msg *gss_msg; 394 int err = 0; 395 396 dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid); 397 gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); 398 if (IS_ERR(gss_msg)) { 399 err = PTR_ERR(gss_msg); 400 goto out; 401 } 402 spin_lock(&gss_auth->lock); 403 if (gss_cred->gc_upcall != NULL) 404 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL); 405 else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { 406 task->tk_timeout = 0; 407 gss_cred->gc_upcall = gss_msg; 408 /* gss_upcall_callback will release the reference to gss_upcall_msg */ 409 atomic_inc(&gss_msg->count); 410 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL); 411 } else 412 err = gss_msg->msg.errno; 413 spin_unlock(&gss_auth->lock); 414 gss_release_msg(gss_msg); 415out: 416 dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid, 417 cred->cr_uid, err); 418 return err; 419} 420 421static inline int 422gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) 423{ 424 struct rpc_cred *cred = &gss_cred->gc_base; 425 struct gss_upcall_msg *gss_msg; 426 DEFINE_WAIT(wait); 427 int err = 0; 428 429 dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid); 430 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 431 if (IS_ERR(gss_msg)) { 432 err = PTR_ERR(gss_msg); 433 goto out; 434 } 435 for (;;) { 436 prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); 437 spin_lock(&gss_auth->lock); 438 if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { 439 spin_unlock(&gss_auth->lock); 440 break; 441 } 442 spin_unlock(&gss_auth->lock); 443 if (signalled()) { 444 err = -ERESTARTSYS; 445 goto out_intr; 446 } 447 schedule(); 448 } 449 if (gss_msg->ctx) 450 gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx)); 451 else 452 err = gss_msg->msg.errno; 453out_intr: 454 finish_wait(&gss_msg->waitqueue, &wait); 455 gss_release_msg(gss_msg); 456out: 457 dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err); 458 return err; 459} 460 461static ssize_t 462gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, 463 char __user *dst, size_t buflen) 464{ 465 char *data = (char *)msg->data + msg->copied; 466 ssize_t mlen = msg->len; 467 ssize_t left; 468 469 if (mlen > buflen) 470 mlen = buflen; 471 left = copy_to_user(dst, data, mlen); 472 if (left < 0) { 473 msg->errno = left; 474 return left; 475 } 476 mlen -= left; 477 msg->copied += mlen; 478 msg->errno = 0; 479 return mlen; 480} 481 482#define MSG_BUF_MAXSIZE 1024 483 484static ssize_t 485gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 486{ 487 const void *p, *end; 488 void *buf; 489 struct rpc_clnt *clnt; 490 struct gss_auth *gss_auth; 491 struct rpc_cred *cred; 492 struct gss_upcall_msg *gss_msg; 493 struct gss_cl_ctx *ctx; 494 uid_t uid; 495 int err = -EFBIG; 496 497 if (mlen > MSG_BUF_MAXSIZE) 498 goto out; 499 err = -ENOMEM; 500 buf = kmalloc(mlen, GFP_KERNEL); 501 if (!buf) 502 goto out; 503 504 clnt = RPC_I(filp->f_dentry->d_inode)->private; 505 err = -EFAULT; 506 if (copy_from_user(buf, src, mlen)) 507 goto err; 508 509 end = (const void *)((char *)buf + mlen); 510 p = simple_get_bytes(buf, end, &uid, sizeof(uid)); 511 if (IS_ERR(p)) { 512 err = PTR_ERR(p); 513 goto err; 514 } 515 516 err = -ENOMEM; 517 ctx = gss_alloc_context(); 518 if (ctx == NULL) 519 goto err; 520 err = 0; 521 gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth); 522 p = gss_fill_context(p, end, ctx, gss_auth->mech); 523 if (IS_ERR(p)) { 524 err = PTR_ERR(p); 525 if (err != -EACCES) 526 goto err_put_ctx; 527 } 528 spin_lock(&gss_auth->lock); 529 gss_msg = __gss_find_upcall(gss_auth, uid); 530 if (gss_msg) { 531 if (err == 0 && gss_msg->ctx == NULL) 532 gss_msg->ctx = gss_get_ctx(ctx); 533 gss_msg->msg.errno = err; 534 __gss_unhash_msg(gss_msg); 535 spin_unlock(&gss_auth->lock); 536 gss_release_msg(gss_msg); 537 } else { 538 struct auth_cred acred = { .uid = uid }; 539 spin_unlock(&gss_auth->lock); 540 cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); 541 if (IS_ERR(cred)) { 542 err = PTR_ERR(cred); 543 goto err_put_ctx; 544 } 545 gss_cred_set_ctx(cred, gss_get_ctx(ctx)); 546 } 547 gss_put_ctx(ctx); 548 kfree(buf); 549 dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen); 550 return mlen; 551err_put_ctx: 552 gss_put_ctx(ctx); 553err: 554 kfree(buf); 555out: 556 dprintk("RPC: gss_pipe_downcall returning %d\n", err); 557 return err; 558} 559 560static void 561gss_pipe_release(struct inode *inode) 562{ 563 struct rpc_inode *rpci = RPC_I(inode); 564 struct rpc_clnt *clnt; 565 struct rpc_auth *auth; 566 struct gss_auth *gss_auth; 567 568 clnt = rpci->private; 569 auth = clnt->cl_auth; 570 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 571 spin_lock(&gss_auth->lock); 572 while (!list_empty(&gss_auth->upcalls)) { 573 struct gss_upcall_msg *gss_msg; 574 575 gss_msg = list_entry(gss_auth->upcalls.next, 576 struct gss_upcall_msg, list); 577 gss_msg->msg.errno = -EPIPE; 578 atomic_inc(&gss_msg->count); 579 __gss_unhash_msg(gss_msg); 580 spin_unlock(&gss_auth->lock); 581 gss_release_msg(gss_msg); 582 spin_lock(&gss_auth->lock); 583 } 584 spin_unlock(&gss_auth->lock); 585} 586 587static void 588gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) 589{ 590 struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); 591 static unsigned long ratelimit; 592 593 if (msg->errno < 0) { 594 dprintk("RPC: gss_pipe_destroy_msg releasing msg %p\n", 595 gss_msg); 596 atomic_inc(&gss_msg->count); 597 gss_unhash_msg(gss_msg); 598 if (msg->errno == -ETIMEDOUT) { 599 unsigned long now = jiffies; 600 if (time_after(now, ratelimit)) { 601 printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n" 602 "Please check user daemon is running!\n"); 603 ratelimit = now + 15*HZ; 604 } 605 } 606 gss_release_msg(gss_msg); 607 } 608} 609 610/* 611 * NOTE: we have the opportunity to use different 612 * parameters based on the input flavor (which must be a pseudoflavor) 613 */ 614static struct rpc_auth * 615gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) 616{ 617 struct gss_auth *gss_auth; 618 struct rpc_auth * auth; 619 int err = -ENOMEM; /* XXX? */ 620 621 dprintk("RPC: creating GSS authenticator for client %p\n",clnt); 622 623 if (!try_module_get(THIS_MODULE)) 624 return ERR_PTR(err); 625 if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) 626 goto out_dec; 627 gss_auth->client = clnt; 628 err = -EINVAL; 629 gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); 630 if (!gss_auth->mech) { 631 printk(KERN_WARNING "%s: Pseudoflavor %d not found!", 632 __FUNCTION__, flavor); 633 goto err_free; 634 } 635 gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); 636 if (gss_auth->service == 0) 637 goto err_put_mech; 638 INIT_LIST_HEAD(&gss_auth->upcalls); 639 spin_lock_init(&gss_auth->lock); 640 auth = &gss_auth->rpc_auth; 641 auth->au_cslack = GSS_CRED_SLACK >> 2; 642 auth->au_rslack = GSS_VERF_SLACK >> 2; 643 auth->au_ops = &authgss_ops; 644 auth->au_flavor = flavor; 645 atomic_set(&auth->au_count, 1); 646 647 err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE); 648 if (err) 649 goto err_put_mech; 650 651 gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, 652 clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 653 if (IS_ERR(gss_auth->dentry)) { 654 err = PTR_ERR(gss_auth->dentry); 655 goto err_put_mech; 656 } 657 658 return auth; 659err_put_mech: 660 gss_mech_put(gss_auth->mech); 661err_free: 662 kfree(gss_auth); 663out_dec: 664 module_put(THIS_MODULE); 665 return ERR_PTR(err); 666} 667 668static void 669gss_destroy(struct rpc_auth *auth) 670{ 671 struct gss_auth *gss_auth; 672 673 dprintk("RPC: destroying GSS authenticator %p flavor %d\n", 674 auth, auth->au_flavor); 675 676 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 677 rpc_unlink(gss_auth->dentry); 678 gss_auth->dentry = NULL; 679 gss_mech_put(gss_auth->mech); 680 681 rpcauth_free_credcache(auth); 682 kfree(gss_auth); 683 module_put(THIS_MODULE); 684} 685 686/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure 687 * to create a new cred or context, so they check that things have been 688 * allocated before freeing them. */ 689static void 690gss_destroy_ctx(struct gss_cl_ctx *ctx) 691{ 692 dprintk("RPC: gss_destroy_ctx\n"); 693 694 if (ctx->gc_gss_ctx) 695 gss_delete_sec_context(&ctx->gc_gss_ctx); 696 697 kfree(ctx->gc_wire_ctx.data); 698 kfree(ctx); 699} 700 701static void 702gss_destroy_cred(struct rpc_cred *rc) 703{ 704 struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base); 705 706 dprintk("RPC: gss_destroy_cred \n"); 707 708 if (cred->gc_ctx) 709 gss_put_ctx(cred->gc_ctx); 710 kfree(cred); 711} 712 713/* 714 * Lookup RPCSEC_GSS cred for the current process 715 */ 716static struct rpc_cred * 717gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) 718{ 719 return rpcauth_lookup_credcache(auth, acred, flags); 720} 721 722static struct rpc_cred * 723gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) 724{ 725 struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); 726 struct gss_cred *cred = NULL; 727 int err = -ENOMEM; 728 729 dprintk("RPC: gss_create_cred for uid %d, flavor %d\n", 730 acred->uid, auth->au_flavor); 731 732 if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL))) 733 goto out_err; 734 735 atomic_set(&cred->gc_count, 1); 736 cred->gc_uid = acred->uid; 737 /* 738 * Note: in order to force a call to call_refresh(), we deliberately 739 * fail to flag the credential as RPCAUTH_CRED_UPTODATE. 740 */ 741 cred->gc_flags = 0; 742 cred->gc_base.cr_ops = &gss_credops; 743 cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; 744 cred->gc_service = gss_auth->service; 745 return &cred->gc_base; 746 747out_err: 748 dprintk("RPC: gss_create_cred failed with error %d\n", err); 749 return ERR_PTR(err); 750} 751 752static int 753gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) 754{ 755 struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); 756 struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); 757 int err; 758 759 do { 760 err = gss_create_upcall(gss_auth, gss_cred); 761 } while (err == -EAGAIN); 762 return err; 763} 764 765static int 766gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) 767{ 768 struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); 769 770 /* 771 * If the searchflags have set RPCAUTH_LOOKUP_NEW, then 772 * we don't really care if the credential has expired or not, 773 * since the caller should be prepared to reinitialise it. 774 */ 775 if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) 776 goto out; 777 /* Don't match with creds that have expired. */ 778 if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) 779 return 0; 780out: 781 return (rc->cr_uid == acred->uid); 782} 783 784/* 785* Marshal credentials. 786* Maybe we should keep a cached credential for performance reasons. 787*/ 788static __be32 * 789gss_marshal(struct rpc_task *task, __be32 *p) 790{ 791 struct rpc_cred *cred = task->tk_msg.rpc_cred; 792 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, 793 gc_base); 794 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 795 __be32 *cred_len; 796 struct rpc_rqst *req = task->tk_rqstp; 797 u32 maj_stat = 0; 798 struct xdr_netobj mic; 799 struct kvec iov; 800 struct xdr_buf verf_buf; 801 802 dprintk("RPC: %4u gss_marshal\n", task->tk_pid); 803 804 *p++ = htonl(RPC_AUTH_GSS); 805 cred_len = p++; 806 807 spin_lock(&ctx->gc_seq_lock); 808 req->rq_seqno = ctx->gc_seq++; 809 spin_unlock(&ctx->gc_seq_lock); 810 811 *p++ = htonl((u32) RPC_GSS_VERSION); 812 *p++ = htonl((u32) ctx->gc_proc); 813 *p++ = htonl((u32) req->rq_seqno); 814 *p++ = htonl((u32) gss_cred->gc_service); 815 p = xdr_encode_netobj(p, &ctx->gc_wire_ctx); 816 *cred_len = htonl((p - (cred_len + 1)) << 2); 817 818 /* We compute the checksum for the verifier over the xdr-encoded bytes 819 * starting with the xid and ending at the end of the credential: */ 820 iov.iov_base = xprt_skip_transport_header(task->tk_xprt, 821 req->rq_snd_buf.head[0].iov_base); 822 iov.iov_len = (u8 *)p - (u8 *)iov.iov_base; 823 xdr_buf_from_iov(&iov, &verf_buf); 824 825 /* set verifier flavor*/ 826 *p++ = htonl(RPC_AUTH_GSS); 827 828 mic.data = (u8 *)(p + 1); 829 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 830 if (maj_stat == GSS_S_CONTEXT_EXPIRED) { 831 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 832 } else if (maj_stat != 0) { 833 printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat); 834 goto out_put_ctx; 835 } 836 p = xdr_encode_opaque(p, NULL, mic.len); 837 gss_put_ctx(ctx); 838 return p; 839out_put_ctx: 840 gss_put_ctx(ctx); 841 return NULL; 842} 843 844/* 845* Refresh credentials. XXX - finish 846*/ 847static int 848gss_refresh(struct rpc_task *task) 849{ 850 851 if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred)) 852 return gss_refresh_upcall(task); 853 return 0; 854} 855 856static __be32 * 857gss_validate(struct rpc_task *task, __be32 *p) 858{ 859 struct rpc_cred *cred = task->tk_msg.rpc_cred; 860 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 861 __be32 seq; 862 struct kvec iov; 863 struct xdr_buf verf_buf; 864 struct xdr_netobj mic; 865 u32 flav,len; 866 u32 maj_stat; 867 868 dprintk("RPC: %4u gss_validate\n", task->tk_pid); 869 870 flav = ntohl(*p++); 871 if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) 872 goto out_bad; 873 if (flav != RPC_AUTH_GSS) 874 goto out_bad; 875 seq = htonl(task->tk_rqstp->rq_seqno); 876 iov.iov_base = &seq; 877 iov.iov_len = sizeof(seq); 878 xdr_buf_from_iov(&iov, &verf_buf); 879 mic.data = (u8 *)p; 880 mic.len = len; 881 882 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 883 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 884 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 885 if (maj_stat) 886 goto out_bad; 887 /* We leave it to unwrap to calculate au_rslack. For now we just 888 * calculate the length of the verifier: */ 889 task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2; 890 gss_put_ctx(ctx); 891 dprintk("RPC: %4u GSS gss_validate: gss_verify_mic succeeded.\n", 892 task->tk_pid); 893 return p + XDR_QUADLEN(len); 894out_bad: 895 gss_put_ctx(ctx); 896 dprintk("RPC: %4u gss_validate failed.\n", task->tk_pid); 897 return NULL; 898} 899 900static inline int 901gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 902 kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj) 903{ 904 struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; 905 struct xdr_buf integ_buf; 906 __be32 *integ_len = NULL; 907 struct xdr_netobj mic; 908 u32 offset; 909 __be32 *q; 910 struct kvec *iov; 911 u32 maj_stat = 0; 912 int status = -EIO; 913 914 integ_len = p++; 915 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; 916 *p++ = htonl(rqstp->rq_seqno); 917 918 status = encode(rqstp, p, obj); 919 if (status) 920 return status; 921 922 if (xdr_buf_subsegment(snd_buf, &integ_buf, 923 offset, snd_buf->len - offset)) 924 return status; 925 *integ_len = htonl(integ_buf.len); 926 927 /* guess whether we're in the head or the tail: */ 928 if (snd_buf->page_len || snd_buf->tail[0].iov_len) 929 iov = snd_buf->tail; 930 else 931 iov = snd_buf->head; 932 p = iov->iov_base + iov->iov_len; 933 mic.data = (u8 *)(p + 1); 934 935 maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic); 936 status = -EIO; /* XXX? */ 937 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 938 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 939 else if (maj_stat) 940 return status; 941 q = xdr_encode_opaque(p, NULL, mic.len); 942 943 offset = (u8 *)q - (u8 *)p; 944 iov->iov_len += offset; 945 snd_buf->len += offset; 946 return 0; 947} 948 949static void 950priv_release_snd_buf(struct rpc_rqst *rqstp) 951{ 952 int i; 953 954 for (i=0; i < rqstp->rq_enc_pages_num; i++) 955 __free_page(rqstp->rq_enc_pages[i]); 956 kfree(rqstp->rq_enc_pages); 957} 958 959static int 960alloc_enc_pages(struct rpc_rqst *rqstp) 961{ 962 struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; 963 int first, last, i; 964 965 if (snd_buf->page_len == 0) { 966 rqstp->rq_enc_pages_num = 0; 967 return 0; 968 } 969 970 first = snd_buf->page_base >> PAGE_CACHE_SHIFT; 971 last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_CACHE_SHIFT; 972 rqstp->rq_enc_pages_num = last - first + 1 + 1; 973 rqstp->rq_enc_pages 974 = kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *), 975 GFP_NOFS); 976 if (!rqstp->rq_enc_pages) 977 goto out; 978 for (i=0; i < rqstp->rq_enc_pages_num; i++) { 979 rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS); 980 if (rqstp->rq_enc_pages[i] == NULL) 981 goto out_free; 982 } 983 rqstp->rq_release_snd_buf = priv_release_snd_buf; 984 return 0; 985out_free: 986 for (i--; i >= 0; i--) { 987 __free_page(rqstp->rq_enc_pages[i]); 988 } 989out: 990 return -EAGAIN; 991} 992 993static inline int 994gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 995 kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj) 996{ 997 struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; 998 u32 offset; 999 u32 maj_stat; 1000 int status; 1001 __be32 *opaque_len; 1002 struct page **inpages; 1003 int first; 1004 int pad; 1005 struct kvec *iov; 1006 char *tmp; 1007 1008 opaque_len = p++; 1009 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; 1010 *p++ = htonl(rqstp->rq_seqno); 1011 1012 status = encode(rqstp, p, obj); 1013 if (status) 1014 return status; 1015 1016 status = alloc_enc_pages(rqstp); 1017 if (status) 1018 return status; 1019 first = snd_buf->page_base >> PAGE_CACHE_SHIFT; 1020 inpages = snd_buf->pages + first; 1021 snd_buf->pages = rqstp->rq_enc_pages; 1022 snd_buf->page_base -= first << PAGE_CACHE_SHIFT; 1023 /* Give the tail its own page, in case we need extra space in the 1024 * head when wrapping: */ 1025 if (snd_buf->page_len || snd_buf->tail[0].iov_len) { 1026 tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]); 1027 memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len); 1028 snd_buf->tail[0].iov_base = tmp; 1029 } 1030 maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages); 1031 /* RPC_SLACK_SPACE should prevent this ever happening: */ 1032 BUG_ON(snd_buf->len > snd_buf->buflen); 1033 status = -EIO; 1034 /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was 1035 * done anyway, so it's safe to put the request on the wire: */ 1036 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1037 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1038 else if (maj_stat) 1039 return status; 1040 1041 *opaque_len = htonl(snd_buf->len - offset); 1042 /* guess whether we're in the head or the tail: */ 1043 if (snd_buf->page_len || snd_buf->tail[0].iov_len) 1044 iov = snd_buf->tail; 1045 else 1046 iov = snd_buf->head; 1047 p = iov->iov_base + iov->iov_len; 1048 pad = 3 - ((snd_buf->len - offset - 1) & 3); 1049 memset(p, 0, pad); 1050 iov->iov_len += pad; 1051 snd_buf->len += pad; 1052 1053 return 0; 1054} 1055 1056static int 1057gss_wrap_req(struct rpc_task *task, 1058 kxdrproc_t encode, void *rqstp, __be32 *p, void *obj) 1059{ 1060 struct rpc_cred *cred = task->tk_msg.rpc_cred; 1061 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, 1062 gc_base); 1063 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 1064 int status = -EIO; 1065 1066 dprintk("RPC: %4u gss_wrap_req\n", task->tk_pid); 1067 if (ctx->gc_proc != RPC_GSS_PROC_DATA) { 1068 /* The spec seems a little ambiguous here, but I think that not 1069 * wrapping context destruction requests makes the most sense. 1070 */ 1071 status = encode(rqstp, p, obj); 1072 goto out; 1073 } 1074 switch (gss_cred->gc_service) { 1075 case RPC_GSS_SVC_NONE: 1076 status = encode(rqstp, p, obj); 1077 break; 1078 case RPC_GSS_SVC_INTEGRITY: 1079 status = gss_wrap_req_integ(cred, ctx, encode, 1080 rqstp, p, obj); 1081 break; 1082 case RPC_GSS_SVC_PRIVACY: 1083 status = gss_wrap_req_priv(cred, ctx, encode, 1084 rqstp, p, obj); 1085 break; 1086 } 1087out: 1088 gss_put_ctx(ctx); 1089 dprintk("RPC: %4u gss_wrap_req returning %d\n", task->tk_pid, status); 1090 return status; 1091} 1092 1093static inline int 1094gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 1095 struct rpc_rqst *rqstp, __be32 **p) 1096{ 1097 struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; 1098 struct xdr_buf integ_buf; 1099 struct xdr_netobj mic; 1100 u32 data_offset, mic_offset; 1101 u32 integ_len; 1102 u32 maj_stat; 1103 int status = -EIO; 1104 1105 integ_len = ntohl(*(*p)++); 1106 if (integ_len & 3) 1107 return status; 1108 data_offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; 1109 mic_offset = integ_len + data_offset; 1110 if (mic_offset > rcv_buf->len) 1111 return status; 1112 if (ntohl(*(*p)++) != rqstp->rq_seqno) 1113 return status; 1114 1115 if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset, 1116 mic_offset - data_offset)) 1117 return status; 1118 1119 if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset)) 1120 return status; 1121 1122 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic); 1123 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1124 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1125 if (maj_stat != GSS_S_COMPLETE) 1126 return status; 1127 return 0; 1128} 1129 1130static inline int 1131gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, 1132 struct rpc_rqst *rqstp, __be32 **p) 1133{ 1134 struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; 1135 u32 offset; 1136 u32 opaque_len; 1137 u32 maj_stat; 1138 int status = -EIO; 1139 1140 opaque_len = ntohl(*(*p)++); 1141 offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base; 1142 if (offset + opaque_len > rcv_buf->len) 1143 return status; 1144 /* remove padding: */ 1145 rcv_buf->len = offset + opaque_len; 1146 1147 maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf); 1148 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 1149 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; 1150 if (maj_stat != GSS_S_COMPLETE) 1151 return status; 1152 if (ntohl(*(*p)++) != rqstp->rq_seqno) 1153 return status; 1154 1155 return 0; 1156} 1157 1158 1159static int 1160gss_unwrap_resp(struct rpc_task *task, 1161 kxdrproc_t decode, void *rqstp, __be32 *p, void *obj) 1162{ 1163 struct rpc_cred *cred = task->tk_msg.rpc_cred; 1164 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, 1165 gc_base); 1166 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); 1167 __be32 *savedp = p; 1168 struct kvec *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head; 1169 int savedlen = head->iov_len; 1170 int status = -EIO; 1171 1172 if (ctx->gc_proc != RPC_GSS_PROC_DATA) 1173 goto out_decode; 1174 switch (gss_cred->gc_service) { 1175 case RPC_GSS_SVC_NONE: 1176 break; 1177 case RPC_GSS_SVC_INTEGRITY: 1178 status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p); 1179 if (status) 1180 goto out; 1181 break; 1182 case RPC_GSS_SVC_PRIVACY: 1183 status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p); 1184 if (status) 1185 goto out; 1186 break; 1187 } 1188 /* take into account extra slack for integrity and privacy cases: */ 1189 task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp) 1190 + (savedlen - head->iov_len); 1191out_decode: 1192 status = decode(rqstp, p, obj); 1193out: 1194 gss_put_ctx(ctx); 1195 dprintk("RPC: %4u gss_unwrap_resp returning %d\n", task->tk_pid, 1196 status); 1197 return status; 1198} 1199 1200static struct rpc_authops authgss_ops = { 1201 .owner = THIS_MODULE, 1202 .au_flavor = RPC_AUTH_GSS, 1203#ifdef RPC_DEBUG 1204 .au_name = "RPCSEC_GSS", 1205#endif 1206 .create = gss_create, 1207 .destroy = gss_destroy, 1208 .lookup_cred = gss_lookup_cred, 1209 .crcreate = gss_create_cred 1210}; 1211 1212static struct rpc_credops gss_credops = { 1213 .cr_name = "AUTH_GSS", 1214 .crdestroy = gss_destroy_cred, 1215 .cr_init = gss_cred_init, 1216 .crmatch = gss_match, 1217 .crmarshal = gss_marshal, 1218 .crrefresh = gss_refresh, 1219 .crvalidate = gss_validate, 1220 .crwrap_req = gss_wrap_req, 1221 .crunwrap_resp = gss_unwrap_resp, 1222}; 1223 1224static struct rpc_pipe_ops gss_upcall_ops = { 1225 .upcall = gss_pipe_upcall, 1226 .downcall = gss_pipe_downcall, 1227 .destroy_msg = gss_pipe_destroy_msg, 1228 .release_pipe = gss_pipe_release, 1229}; 1230 1231/* 1232 * Initialize RPCSEC_GSS module 1233 */ 1234static int __init init_rpcsec_gss(void) 1235{ 1236 int err = 0; 1237 1238 err = rpcauth_register(&authgss_ops); 1239 if (err) 1240 goto out; 1241 err = gss_svc_init(); 1242 if (err) 1243 goto out_unregister; 1244 return 0; 1245out_unregister: 1246 rpcauth_unregister(&authgss_ops); 1247out: 1248 return err; 1249} 1250 1251static void __exit exit_rpcsec_gss(void) 1252{ 1253 gss_svc_shutdown(); 1254 rpcauth_unregister(&authgss_ops); 1255} 1256 1257MODULE_LICENSE("GPL"); 1258module_init(init_rpcsec_gss) 1259module_exit(exit_rpcsec_gss) 1260