1 #include <linux/types.h> 2 #include <linux/sched.h> 3 #include <linux/module.h> 4 #include <linux/sunrpc/types.h> 5 #include <linux/sunrpc/xdr.h> 6 #include <linux/sunrpc/svcsock.h> 7 #include <linux/sunrpc/svcauth.h> 8 #include <linux/sunrpc/gss_api.h> 9 #include <linux/err.h> 10 #include <linux/seq_file.h> 11 #include <linux/hash.h> 12 #include <linux/string.h> 13 #include <net/sock.h> 14 #include <net/ipv6.h> 15 #include <linux/kernel.h> 16 #define RPCDBG_FACILITY RPCDBG_AUTH 17 18 19 /* 20 * AUTHUNIX and AUTHNULL credentials are both handled here. 21 * AUTHNULL is treated just like AUTHUNIX except that the uid/gid 22 * are always nobody (-2). i.e. we do the same IP address checks for 23 * AUTHNULL as for AUTHUNIX, and that is done here. 24 */ 25 26 27 struct unix_domain { 28 struct auth_domain h; 29 int addr_changes; 30 /* other stuff later */ 31 }; 32 33 extern struct auth_ops svcauth_unix; 34 35 struct auth_domain *unix_domain_find(char *name) 36 { 37 struct auth_domain *rv; 38 struct unix_domain *new = NULL; 39 40 rv = auth_domain_lookup(name, NULL); 41 while(1) { 42 if (rv) { 43 if (new && rv != &new->h) 44 auth_domain_put(&new->h); 45 46 if (rv->flavour != &svcauth_unix) { 47 auth_domain_put(rv); 48 return NULL; 49 } 50 return rv; 51 } 52 53 new = kmalloc(sizeof(*new), GFP_KERNEL); 54 if (new == NULL) 55 return NULL; 56 kref_init(&new->h.ref); 57 new->h.name = kstrdup(name, GFP_KERNEL); 58 if (new->h.name == NULL) { 59 kfree(new); 60 return NULL; 61 } 62 new->h.flavour = &svcauth_unix; 63 new->addr_changes = 0; 64 rv = auth_domain_lookup(name, &new->h); 65 } 66 } 67 EXPORT_SYMBOL(unix_domain_find); 68 69 static void svcauth_unix_domain_release(struct auth_domain *dom) 70 { 71 struct unix_domain *ud = container_of(dom, struct unix_domain, h); 72 73 kfree(dom->name); 74 kfree(ud); 75 } 76 77 78 /************************************************** 79 * cache for IP address to unix_domain 80 * as needed by AUTH_UNIX 81 */ 82 #define IP_HASHBITS 8 83 #define IP_HASHMAX (1<<IP_HASHBITS) 84 #define IP_HASHMASK (IP_HASHMAX-1) 85 86 struct ip_map { 87 struct cache_head h; 88 char m_class[8]; /* e.g. "nfsd" */ 89 struct in6_addr m_addr; 90 struct unix_domain *m_client; 91 int m_add_change; 92 }; 93 static struct cache_head *ip_table[IP_HASHMAX]; 94 95 static void ip_map_put(struct kref *kref) 96 { 97 struct cache_head *item = container_of(kref, struct cache_head, ref); 98 struct ip_map *im = container_of(item, struct ip_map,h); 99 100 if (test_bit(CACHE_VALID, &item->flags) && 101 !test_bit(CACHE_NEGATIVE, &item->flags)) 102 auth_domain_put(&im->m_client->h); 103 kfree(im); 104 } 105 106 #if IP_HASHBITS == 8 107 /* hash_long on a 64 bit machine is currently REALLY BAD for 108 * IP addresses in reverse-endian (i.e. on a little-endian machine). 109 * So use a trivial but reliable hash instead 110 */ 111 static inline int hash_ip(__be32 ip) 112 { 113 int hash = (__force u32)ip ^ ((__force u32)ip>>16); 114 return (hash ^ (hash>>8)) & 0xff; 115 } 116 #endif 117 static inline int hash_ip6(struct in6_addr ip) 118 { 119 return (hash_ip(ip.s6_addr32[0]) ^ 120 hash_ip(ip.s6_addr32[1]) ^ 121 hash_ip(ip.s6_addr32[2]) ^ 122 hash_ip(ip.s6_addr32[3])); 123 } 124 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) 125 { 126 struct ip_map *orig = container_of(corig, struct ip_map, h); 127 struct ip_map *new = container_of(cnew, struct ip_map, h); 128 return strcmp(orig->m_class, new->m_class) == 0 129 && ipv6_addr_equal(&orig->m_addr, &new->m_addr); 130 } 131 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem) 132 { 133 struct ip_map *new = container_of(cnew, struct ip_map, h); 134 struct ip_map *item = container_of(citem, struct ip_map, h); 135 136 strcpy(new->m_class, item->m_class); 137 ipv6_addr_copy(&new->m_addr, &item->m_addr); 138 } 139 static void update(struct cache_head *cnew, struct cache_head *citem) 140 { 141 struct ip_map *new = container_of(cnew, struct ip_map, h); 142 struct ip_map *item = container_of(citem, struct ip_map, h); 143 144 kref_get(&item->m_client->h.ref); 145 new->m_client = item->m_client; 146 new->m_add_change = item->m_add_change; 147 } 148 static struct cache_head *ip_map_alloc(void) 149 { 150 struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL); 151 if (i) 152 return &i->h; 153 else 154 return NULL; 155 } 156 157 static void ip_map_request(struct cache_detail *cd, 158 struct cache_head *h, 159 char **bpp, int *blen) 160 { 161 char text_addr[40]; 162 struct ip_map *im = container_of(h, struct ip_map, h); 163 164 if (ipv6_addr_v4mapped(&(im->m_addr))) { 165 snprintf(text_addr, 20, NIPQUAD_FMT, 166 ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff, 167 ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff, 168 ntohl(im->m_addr.s6_addr32[3]) >> 8 & 0xff, 169 ntohl(im->m_addr.s6_addr32[3]) >> 0 & 0xff); 170 } else { 171 snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr)); 172 } 173 qword_add(bpp, blen, im->m_class); 174 qword_add(bpp, blen, text_addr); 175 (*bpp)[-1] = '\n'; 176 } 177 178 static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr); 179 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry); 180 181 static int ip_map_parse(struct cache_detail *cd, 182 char *mesg, int mlen) 183 { 184 /* class ipaddress [domainname] */ 185 /* should be safe just to use the start of the input buffer 186 * for scratch: */ 187 char *buf = mesg; 188 int len; 189 int b1, b2, b3, b4, b5, b6, b7, b8; 190 char c; 191 char class[8]; 192 struct in6_addr addr; 193 int err; 194 195 struct ip_map *ipmp; 196 struct auth_domain *dom; 197 time_t expiry; 198 199 if (mesg[mlen-1] != '\n') 200 return -EINVAL; 201 mesg[mlen-1] = 0; 202 203 /* class */ 204 len = qword_get(&mesg, class, sizeof(class)); 205 if (len <= 0) return -EINVAL; 206 207 /* ip address */ 208 len = qword_get(&mesg, buf, mlen); 209 if (len <= 0) return -EINVAL; 210 211 if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) { 212 addr.s6_addr32[0] = 0; 213 addr.s6_addr32[1] = 0; 214 addr.s6_addr32[2] = htonl(0xffff); 215 addr.s6_addr32[3] = 216 htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); 217 } else if (sscanf(buf, NIP6_FMT "%c", 218 &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) { 219 addr.s6_addr16[0] = htons(b1); 220 addr.s6_addr16[1] = htons(b2); 221 addr.s6_addr16[2] = htons(b3); 222 addr.s6_addr16[3] = htons(b4); 223 addr.s6_addr16[4] = htons(b5); 224 addr.s6_addr16[5] = htons(b6); 225 addr.s6_addr16[6] = htons(b7); 226 addr.s6_addr16[7] = htons(b8); 227 } else 228 return -EINVAL; 229 230 expiry = get_expiry(&mesg); 231 if (expiry ==0) 232 return -EINVAL; 233 234 /* domainname, or empty for NEGATIVE */ 235 len = qword_get(&mesg, buf, mlen); 236 if (len < 0) return -EINVAL; 237 238 if (len) { 239 dom = unix_domain_find(buf); 240 if (dom == NULL) 241 return -ENOENT; 242 } else 243 dom = NULL; 244 245 ipmp = ip_map_lookup(class, &addr); 246 if (ipmp) { 247 err = ip_map_update(ipmp, 248 container_of(dom, struct unix_domain, h), 249 expiry); 250 } else 251 err = -ENOMEM; 252 253 if (dom) 254 auth_domain_put(dom); 255 256 cache_flush(); 257 return err; 258 } 259 260 static int ip_map_show(struct seq_file *m, 261 struct cache_detail *cd, 262 struct cache_head *h) 263 { 264 struct ip_map *im; 265 struct in6_addr addr; 266 char *dom = "-no-domain-"; 267 268 if (h == NULL) { 269 seq_puts(m, "#class IP domain\n"); 270 return 0; 271 } 272 im = container_of(h, struct ip_map, h); 273 /* class addr domain */ 274 ipv6_addr_copy(&addr, &im->m_addr); 275 276 if (test_bit(CACHE_VALID, &h->flags) && 277 !test_bit(CACHE_NEGATIVE, &h->flags)) 278 dom = im->m_client->h.name; 279 280 if (ipv6_addr_v4mapped(&addr)) { 281 seq_printf(m, "%s " NIPQUAD_FMT " %s\n", 282 im->m_class, 283 ntohl(addr.s6_addr32[3]) >> 24 & 0xff, 284 ntohl(addr.s6_addr32[3]) >> 16 & 0xff, 285 ntohl(addr.s6_addr32[3]) >> 8 & 0xff, 286 ntohl(addr.s6_addr32[3]) >> 0 & 0xff, 287 dom); 288 } else { 289 seq_printf(m, "%s " NIP6_FMT " %s\n", 290 im->m_class, NIP6(addr), dom); 291 } 292 return 0; 293 } 294 295 296 struct cache_detail ip_map_cache = { 297 .owner = THIS_MODULE, 298 .hash_size = IP_HASHMAX, 299 .hash_table = ip_table, 300 .name = "auth.unix.ip", 301 .cache_put = ip_map_put, 302 .cache_request = ip_map_request, 303 .cache_parse = ip_map_parse, 304 .cache_show = ip_map_show, 305 .match = ip_map_match, 306 .init = ip_map_init, 307 .update = update, 308 .alloc = ip_map_alloc, 309 }; 310 311 static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr) 312 { 313 struct ip_map ip; 314 struct cache_head *ch; 315 316 strcpy(ip.m_class, class); 317 ipv6_addr_copy(&ip.m_addr, addr); 318 ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h, 319 hash_str(class, IP_HASHBITS) ^ 320 hash_ip6(*addr)); 321 322 if (ch) 323 return container_of(ch, struct ip_map, h); 324 else 325 return NULL; 326 } 327 328 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry) 329 { 330 struct ip_map ip; 331 struct cache_head *ch; 332 333 ip.m_client = udom; 334 ip.h.flags = 0; 335 if (!udom) 336 set_bit(CACHE_NEGATIVE, &ip.h.flags); 337 else { 338 ip.m_add_change = udom->addr_changes; 339 /* if this is from the legacy set_client system call, 340 * we need m_add_change to be one higher 341 */ 342 if (expiry == NEVER) 343 ip.m_add_change++; 344 } 345 ip.h.expiry_time = expiry; 346 ch = sunrpc_cache_update(&ip_map_cache, 347 &ip.h, &ipm->h, 348 hash_str(ipm->m_class, IP_HASHBITS) ^ 349 hash_ip6(ipm->m_addr)); 350 if (!ch) 351 return -ENOMEM; 352 cache_put(ch, &ip_map_cache); 353 return 0; 354 } 355 356 int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom) 357 { 358 struct unix_domain *udom; 359 struct ip_map *ipmp; 360 361 if (dom->flavour != &svcauth_unix) 362 return -EINVAL; 363 udom = container_of(dom, struct unix_domain, h); 364 ipmp = ip_map_lookup("nfsd", addr); 365 366 if (ipmp) 367 return ip_map_update(ipmp, udom, NEVER); 368 else 369 return -ENOMEM; 370 } 371 EXPORT_SYMBOL(auth_unix_add_addr); 372 373 int auth_unix_forget_old(struct auth_domain *dom) 374 { 375 struct unix_domain *udom; 376 377 if (dom->flavour != &svcauth_unix) 378 return -EINVAL; 379 udom = container_of(dom, struct unix_domain, h); 380 udom->addr_changes++; 381 return 0; 382 } 383 EXPORT_SYMBOL(auth_unix_forget_old); 384 385 struct auth_domain *auth_unix_lookup(struct in6_addr *addr) 386 { 387 struct ip_map *ipm; 388 struct auth_domain *rv; 389 390 ipm = ip_map_lookup("nfsd", addr); 391 392 if (!ipm) 393 return NULL; 394 if (cache_check(&ip_map_cache, &ipm->h, NULL)) 395 return NULL; 396 397 if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { 398 if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0) 399 auth_domain_put(&ipm->m_client->h); 400 rv = NULL; 401 } else { 402 rv = &ipm->m_client->h; 403 kref_get(&rv->ref); 404 } 405 cache_put(&ipm->h, &ip_map_cache); 406 return rv; 407 } 408 EXPORT_SYMBOL(auth_unix_lookup); 409 410 void svcauth_unix_purge(void) 411 { 412 cache_purge(&ip_map_cache); 413 } 414 EXPORT_SYMBOL(svcauth_unix_purge); 415 416 static inline struct ip_map * 417 ip_map_cached_get(struct svc_rqst *rqstp) 418 { 419 struct ip_map *ipm = NULL; 420 struct svc_xprt *xprt = rqstp->rq_xprt; 421 422 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { 423 spin_lock(&xprt->xpt_lock); 424 ipm = xprt->xpt_auth_cache; 425 if (ipm != NULL) { 426 if (!cache_valid(&ipm->h)) { 427 /* 428 * The entry has been invalidated since it was 429 * remembered, e.g. by a second mount from the 430 * same IP address. 431 */ 432 xprt->xpt_auth_cache = NULL; 433 spin_unlock(&xprt->xpt_lock); 434 cache_put(&ipm->h, &ip_map_cache); 435 return NULL; 436 } 437 cache_get(&ipm->h); 438 } 439 spin_unlock(&xprt->xpt_lock); 440 } 441 return ipm; 442 } 443 444 static inline void 445 ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) 446 { 447 struct svc_xprt *xprt = rqstp->rq_xprt; 448 449 if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) { 450 spin_lock(&xprt->xpt_lock); 451 if (xprt->xpt_auth_cache == NULL) { 452 /* newly cached, keep the reference */ 453 xprt->xpt_auth_cache = ipm; 454 ipm = NULL; 455 } 456 spin_unlock(&xprt->xpt_lock); 457 } 458 if (ipm) 459 cache_put(&ipm->h, &ip_map_cache); 460 } 461 462 void 463 svcauth_unix_info_release(void *info) 464 { 465 struct ip_map *ipm = info; 466 cache_put(&ipm->h, &ip_map_cache); 467 } 468 469 /**************************************************************************** 470 * auth.unix.gid cache 471 * simple cache to map a UID to a list of GIDs 472 * because AUTH_UNIX aka AUTH_SYS has a max of 16 473 */ 474 #define GID_HASHBITS 8 475 #define GID_HASHMAX (1<<GID_HASHBITS) 476 #define GID_HASHMASK (GID_HASHMAX - 1) 477 478 struct unix_gid { 479 struct cache_head h; 480 uid_t uid; 481 struct group_info *gi; 482 }; 483 static struct cache_head *gid_table[GID_HASHMAX]; 484 485 static void unix_gid_put(struct kref *kref) 486 { 487 struct cache_head *item = container_of(kref, struct cache_head, ref); 488 struct unix_gid *ug = container_of(item, struct unix_gid, h); 489 if (test_bit(CACHE_VALID, &item->flags) && 490 !test_bit(CACHE_NEGATIVE, &item->flags)) 491 put_group_info(ug->gi); 492 kfree(ug); 493 } 494 495 static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) 496 { 497 struct unix_gid *orig = container_of(corig, struct unix_gid, h); 498 struct unix_gid *new = container_of(cnew, struct unix_gid, h); 499 return orig->uid == new->uid; 500 } 501 static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) 502 { 503 struct unix_gid *new = container_of(cnew, struct unix_gid, h); 504 struct unix_gid *item = container_of(citem, struct unix_gid, h); 505 new->uid = item->uid; 506 } 507 static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem) 508 { 509 struct unix_gid *new = container_of(cnew, struct unix_gid, h); 510 struct unix_gid *item = container_of(citem, struct unix_gid, h); 511 512 get_group_info(item->gi); 513 new->gi = item->gi; 514 } 515 static struct cache_head *unix_gid_alloc(void) 516 { 517 struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL); 518 if (g) 519 return &g->h; 520 else 521 return NULL; 522 } 523 524 static void unix_gid_request(struct cache_detail *cd, 525 struct cache_head *h, 526 char **bpp, int *blen) 527 { 528 char tuid[20]; 529 struct unix_gid *ug = container_of(h, struct unix_gid, h); 530 531 snprintf(tuid, 20, "%u", ug->uid); 532 qword_add(bpp, blen, tuid); 533 (*bpp)[-1] = '\n'; 534 } 535 536 static struct unix_gid *unix_gid_lookup(uid_t uid); 537 extern struct cache_detail unix_gid_cache; 538 539 static int unix_gid_parse(struct cache_detail *cd, 540 char *mesg, int mlen) 541 { 542 /* uid expiry Ngid gid0 gid1 ... gidN-1 */ 543 int uid; 544 int gids; 545 int rv; 546 int i; 547 int err; 548 time_t expiry; 549 struct unix_gid ug, *ugp; 550 551 if (mlen <= 0 || mesg[mlen-1] != '\n') 552 return -EINVAL; 553 mesg[mlen-1] = 0; 554 555 rv = get_int(&mesg, &uid); 556 if (rv) 557 return -EINVAL; 558 ug.uid = uid; 559 560 expiry = get_expiry(&mesg); 561 if (expiry == 0) 562 return -EINVAL; 563 564 rv = get_int(&mesg, &gids); 565 if (rv || gids < 0 || gids > 8192) 566 return -EINVAL; 567 568 ug.gi = groups_alloc(gids); 569 if (!ug.gi) 570 return -ENOMEM; 571 572 for (i = 0 ; i < gids ; i++) { 573 int gid; 574 rv = get_int(&mesg, &gid); 575 err = -EINVAL; 576 if (rv) 577 goto out; 578 GROUP_AT(ug.gi, i) = gid; 579 } 580 581 ugp = unix_gid_lookup(uid); 582 if (ugp) { 583 struct cache_head *ch; 584 ug.h.flags = 0; 585 ug.h.expiry_time = expiry; 586 ch = sunrpc_cache_update(&unix_gid_cache, 587 &ug.h, &ugp->h, 588 hash_long(uid, GID_HASHBITS)); 589 if (!ch) 590 err = -ENOMEM; 591 else { 592 err = 0; 593 cache_put(ch, &unix_gid_cache); 594 } 595 } else 596 err = -ENOMEM; 597 out: 598 if (ug.gi) 599 put_group_info(ug.gi); 600 return err; 601 } 602 603 static int unix_gid_show(struct seq_file *m, 604 struct cache_detail *cd, 605 struct cache_head *h) 606 { 607 struct unix_gid *ug; 608 int i; 609 int glen; 610 611 if (h == NULL) { 612 seq_puts(m, "#uid cnt: gids...\n"); 613 return 0; 614 } 615 ug = container_of(h, struct unix_gid, h); 616 if (test_bit(CACHE_VALID, &h->flags) && 617 !test_bit(CACHE_NEGATIVE, &h->flags)) 618 glen = ug->gi->ngroups; 619 else 620 glen = 0; 621 622 seq_printf(m, "%d %d:", ug->uid, glen); 623 for (i = 0; i < glen; i++) 624 seq_printf(m, " %d", GROUP_AT(ug->gi, i)); 625 seq_printf(m, "\n"); 626 return 0; 627 } 628 629 struct cache_detail unix_gid_cache = { 630 .owner = THIS_MODULE, 631 .hash_size = GID_HASHMAX, 632 .hash_table = gid_table, 633 .name = "auth.unix.gid", 634 .cache_put = unix_gid_put, 635 .cache_request = unix_gid_request, 636 .cache_parse = unix_gid_parse, 637 .cache_show = unix_gid_show, 638 .match = unix_gid_match, 639 .init = unix_gid_init, 640 .update = unix_gid_update, 641 .alloc = unix_gid_alloc, 642 }; 643 644 static struct unix_gid *unix_gid_lookup(uid_t uid) 645 { 646 struct unix_gid ug; 647 struct cache_head *ch; 648 649 ug.uid = uid; 650 ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h, 651 hash_long(uid, GID_HASHBITS)); 652 if (ch) 653 return container_of(ch, struct unix_gid, h); 654 else 655 return NULL; 656 } 657 658 static int unix_gid_find(uid_t uid, struct group_info **gip, 659 struct svc_rqst *rqstp) 660 { 661 struct unix_gid *ug = unix_gid_lookup(uid); 662 if (!ug) 663 return -EAGAIN; 664 switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) { 665 case -ENOENT: 666 *gip = NULL; 667 return 0; 668 case 0: 669 *gip = ug->gi; 670 get_group_info(*gip); 671 return 0; 672 default: 673 return -EAGAIN; 674 } 675 } 676 677 int 678 svcauth_unix_set_client(struct svc_rqst *rqstp) 679 { 680 struct sockaddr_in *sin; 681 struct sockaddr_in6 *sin6, sin6_storage; 682 struct ip_map *ipm; 683 684 switch (rqstp->rq_addr.ss_family) { 685 case AF_INET: 686 sin = svc_addr_in(rqstp); 687 sin6 = &sin6_storage; 688 ipv6_addr_set(&sin6->sin6_addr, 0, 0, 689 htonl(0x0000FFFF), sin->sin_addr.s_addr); 690 break; 691 case AF_INET6: 692 sin6 = svc_addr_in6(rqstp); 693 break; 694 default: 695 BUG(); 696 } 697 698 rqstp->rq_client = NULL; 699 if (rqstp->rq_proc == 0) 700 return SVC_OK; 701 702 ipm = ip_map_cached_get(rqstp); 703 if (ipm == NULL) 704 ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, 705 &sin6->sin6_addr); 706 707 if (ipm == NULL) 708 return SVC_DENIED; 709 710 switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { 711 default: 712 BUG(); 713 case -EAGAIN: 714 case -ETIMEDOUT: 715 return SVC_DROP; 716 case -ENOENT: 717 return SVC_DENIED; 718 case 0: 719 rqstp->rq_client = &ipm->m_client->h; 720 kref_get(&rqstp->rq_client->ref); 721 ip_map_cached_put(rqstp, ipm); 722 break; 723 } 724 return SVC_OK; 725 } 726 727 EXPORT_SYMBOL(svcauth_unix_set_client); 728 729 static int 730 svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) 731 { 732 struct kvec *argv = &rqstp->rq_arg.head[0]; 733 struct kvec *resv = &rqstp->rq_res.head[0]; 734 struct svc_cred *cred = &rqstp->rq_cred; 735 736 cred->cr_group_info = NULL; 737 rqstp->rq_client = NULL; 738 739 if (argv->iov_len < 3*4) 740 return SVC_GARBAGE; 741 742 if (svc_getu32(argv) != 0) { 743 dprintk("svc: bad null cred\n"); 744 *authp = rpc_autherr_badcred; 745 return SVC_DENIED; 746 } 747 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 748 dprintk("svc: bad null verf\n"); 749 *authp = rpc_autherr_badverf; 750 return SVC_DENIED; 751 } 752 753 /* Signal that mapping to nobody uid/gid is required */ 754 cred->cr_uid = (uid_t) -1; 755 cred->cr_gid = (gid_t) -1; 756 cred->cr_group_info = groups_alloc(0); 757 if (cred->cr_group_info == NULL) 758 return SVC_DROP; /* kmalloc failure - client must retry */ 759 760 /* Put NULL verifier */ 761 svc_putnl(resv, RPC_AUTH_NULL); 762 svc_putnl(resv, 0); 763 764 rqstp->rq_flavor = RPC_AUTH_NULL; 765 return SVC_OK; 766 } 767 768 static int 769 svcauth_null_release(struct svc_rqst *rqstp) 770 { 771 if (rqstp->rq_client) 772 auth_domain_put(rqstp->rq_client); 773 rqstp->rq_client = NULL; 774 if (rqstp->rq_cred.cr_group_info) 775 put_group_info(rqstp->rq_cred.cr_group_info); 776 rqstp->rq_cred.cr_group_info = NULL; 777 778 return 0; /* don't drop */ 779 } 780 781 782 struct auth_ops svcauth_null = { 783 .name = "null", 784 .owner = THIS_MODULE, 785 .flavour = RPC_AUTH_NULL, 786 .accept = svcauth_null_accept, 787 .release = svcauth_null_release, 788 .set_client = svcauth_unix_set_client, 789 }; 790 791 792 static int 793 svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) 794 { 795 struct kvec *argv = &rqstp->rq_arg.head[0]; 796 struct kvec *resv = &rqstp->rq_res.head[0]; 797 struct svc_cred *cred = &rqstp->rq_cred; 798 u32 slen, i; 799 int len = argv->iov_len; 800 801 cred->cr_group_info = NULL; 802 rqstp->rq_client = NULL; 803 804 if ((len -= 3*4) < 0) 805 return SVC_GARBAGE; 806 807 svc_getu32(argv); /* length */ 808 svc_getu32(argv); /* time stamp */ 809 slen = XDR_QUADLEN(svc_getnl(argv)); /* machname length */ 810 if (slen > 64 || (len -= (slen + 3)*4) < 0) 811 goto badcred; 812 argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ 813 argv->iov_len -= slen*4; 814 815 cred->cr_uid = svc_getnl(argv); /* uid */ 816 cred->cr_gid = svc_getnl(argv); /* gid */ 817 slen = svc_getnl(argv); /* gids length */ 818 if (slen > 16 || (len -= (slen + 2)*4) < 0) 819 goto badcred; 820 if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp) 821 == -EAGAIN) 822 return SVC_DROP; 823 if (cred->cr_group_info == NULL) { 824 cred->cr_group_info = groups_alloc(slen); 825 if (cred->cr_group_info == NULL) 826 return SVC_DROP; 827 for (i = 0; i < slen; i++) 828 GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); 829 } else { 830 for (i = 0; i < slen ; i++) 831 svc_getnl(argv); 832 } 833 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 834 *authp = rpc_autherr_badverf; 835 return SVC_DENIED; 836 } 837 838 /* Put NULL verifier */ 839 svc_putnl(resv, RPC_AUTH_NULL); 840 svc_putnl(resv, 0); 841 842 rqstp->rq_flavor = RPC_AUTH_UNIX; 843 return SVC_OK; 844 845 badcred: 846 *authp = rpc_autherr_badcred; 847 return SVC_DENIED; 848 } 849 850 static int 851 svcauth_unix_release(struct svc_rqst *rqstp) 852 { 853 /* Verifier (such as it is) is already in place. 854 */ 855 if (rqstp->rq_client) 856 auth_domain_put(rqstp->rq_client); 857 rqstp->rq_client = NULL; 858 if (rqstp->rq_cred.cr_group_info) 859 put_group_info(rqstp->rq_cred.cr_group_info); 860 rqstp->rq_cred.cr_group_info = NULL; 861 862 return 0; 863 } 864 865 866 struct auth_ops svcauth_unix = { 867 .name = "unix", 868 .owner = THIS_MODULE, 869 .flavour = RPC_AUTH_UNIX, 870 .accept = svcauth_unix_accept, 871 .release = svcauth_unix_release, 872 .domain_release = svcauth_unix_domain_release, 873 .set_client = svcauth_unix_set_client, 874 }; 875 876