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/err.h> 9 #include <linux/seq_file.h> 10 #include <linux/hash.h> 11 #include <linux/string.h> 12 #include <net/sock.h> 13 14 #define RPCDBG_FACILITY RPCDBG_AUTH 15 16 17 /* 18 * AUTHUNIX and AUTHNULL credentials are both handled here. 19 * AUTHNULL is treated just like AUTHUNIX except that the uid/gid 20 * are always nobody (-2). i.e. we do the same IP address checks for 21 * AUTHNULL as for AUTHUNIX, and that is done here. 22 */ 23 24 25 struct unix_domain { 26 struct auth_domain h; 27 int addr_changes; 28 /* other stuff later */ 29 }; 30 31 extern struct auth_ops svcauth_unix; 32 33 struct auth_domain *unix_domain_find(char *name) 34 { 35 struct auth_domain *rv; 36 struct unix_domain *new = NULL; 37 38 rv = auth_domain_lookup(name, NULL); 39 while(1) { 40 if (rv) { 41 if (new && rv != &new->h) 42 auth_domain_put(&new->h); 43 44 if (rv->flavour != &svcauth_unix) { 45 auth_domain_put(rv); 46 return NULL; 47 } 48 return rv; 49 } 50 51 new = kmalloc(sizeof(*new), GFP_KERNEL); 52 if (new == NULL) 53 return NULL; 54 kref_init(&new->h.ref); 55 new->h.name = kstrdup(name, GFP_KERNEL); 56 if (new->h.name == NULL) { 57 kfree(new); 58 return NULL; 59 } 60 new->h.flavour = &svcauth_unix; 61 new->addr_changes = 0; 62 rv = auth_domain_lookup(name, &new->h); 63 } 64 } 65 66 static void svcauth_unix_domain_release(struct auth_domain *dom) 67 { 68 struct unix_domain *ud = container_of(dom, struct unix_domain, h); 69 70 kfree(dom->name); 71 kfree(ud); 72 } 73 74 75 /************************************************** 76 * cache for IP address to unix_domain 77 * as needed by AUTH_UNIX 78 */ 79 #define IP_HASHBITS 8 80 #define IP_HASHMAX (1<<IP_HASHBITS) 81 #define IP_HASHMASK (IP_HASHMAX-1) 82 83 struct ip_map { 84 struct cache_head h; 85 char m_class[8]; /* e.g. "nfsd" */ 86 struct in_addr m_addr; 87 struct unix_domain *m_client; 88 int m_add_change; 89 }; 90 static struct cache_head *ip_table[IP_HASHMAX]; 91 92 static void ip_map_put(struct kref *kref) 93 { 94 struct cache_head *item = container_of(kref, struct cache_head, ref); 95 struct ip_map *im = container_of(item, struct ip_map,h); 96 97 if (test_bit(CACHE_VALID, &item->flags) && 98 !test_bit(CACHE_NEGATIVE, &item->flags)) 99 auth_domain_put(&im->m_client->h); 100 kfree(im); 101 } 102 103 #if IP_HASHBITS == 8 104 /* hash_long on a 64 bit machine is currently REALLY BAD for 105 * IP addresses in reverse-endian (i.e. on a little-endian machine). 106 * So use a trivial but reliable hash instead 107 */ 108 static inline int hash_ip(__be32 ip) 109 { 110 int hash = (__force u32)ip ^ ((__force u32)ip>>16); 111 return (hash ^ (hash>>8)) & 0xff; 112 } 113 #endif 114 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) 115 { 116 struct ip_map *orig = container_of(corig, struct ip_map, h); 117 struct ip_map *new = container_of(cnew, struct ip_map, h); 118 return strcmp(orig->m_class, new->m_class) == 0 119 && orig->m_addr.s_addr == new->m_addr.s_addr; 120 } 121 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem) 122 { 123 struct ip_map *new = container_of(cnew, struct ip_map, h); 124 struct ip_map *item = container_of(citem, struct ip_map, h); 125 126 strcpy(new->m_class, item->m_class); 127 new->m_addr.s_addr = item->m_addr.s_addr; 128 } 129 static void update(struct cache_head *cnew, struct cache_head *citem) 130 { 131 struct ip_map *new = container_of(cnew, struct ip_map, h); 132 struct ip_map *item = container_of(citem, struct ip_map, h); 133 134 kref_get(&item->m_client->h.ref); 135 new->m_client = item->m_client; 136 new->m_add_change = item->m_add_change; 137 } 138 static struct cache_head *ip_map_alloc(void) 139 { 140 struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL); 141 if (i) 142 return &i->h; 143 else 144 return NULL; 145 } 146 147 static void ip_map_request(struct cache_detail *cd, 148 struct cache_head *h, 149 char **bpp, int *blen) 150 { 151 char text_addr[20]; 152 struct ip_map *im = container_of(h, struct ip_map, h); 153 __be32 addr = im->m_addr.s_addr; 154 155 snprintf(text_addr, 20, "%u.%u.%u.%u", 156 ntohl(addr) >> 24 & 0xff, 157 ntohl(addr) >> 16 & 0xff, 158 ntohl(addr) >> 8 & 0xff, 159 ntohl(addr) >> 0 & 0xff); 160 161 qword_add(bpp, blen, im->m_class); 162 qword_add(bpp, blen, text_addr); 163 (*bpp)[-1] = '\n'; 164 } 165 166 static struct ip_map *ip_map_lookup(char *class, struct in_addr addr); 167 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry); 168 169 static int ip_map_parse(struct cache_detail *cd, 170 char *mesg, int mlen) 171 { 172 /* class ipaddress [domainname] */ 173 /* should be safe just to use the start of the input buffer 174 * for scratch: */ 175 char *buf = mesg; 176 int len; 177 int b1,b2,b3,b4; 178 char c; 179 char class[8]; 180 struct in_addr addr; 181 int err; 182 183 struct ip_map *ipmp; 184 struct auth_domain *dom; 185 time_t expiry; 186 187 if (mesg[mlen-1] != '\n') 188 return -EINVAL; 189 mesg[mlen-1] = 0; 190 191 /* class */ 192 len = qword_get(&mesg, class, sizeof(class)); 193 if (len <= 0) return -EINVAL; 194 195 /* ip address */ 196 len = qword_get(&mesg, buf, mlen); 197 if (len <= 0) return -EINVAL; 198 199 if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4) 200 return -EINVAL; 201 202 expiry = get_expiry(&mesg); 203 if (expiry ==0) 204 return -EINVAL; 205 206 /* domainname, or empty for NEGATIVE */ 207 len = qword_get(&mesg, buf, mlen); 208 if (len < 0) return -EINVAL; 209 210 if (len) { 211 dom = unix_domain_find(buf); 212 if (dom == NULL) 213 return -ENOENT; 214 } else 215 dom = NULL; 216 217 addr.s_addr = 218 htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); 219 220 ipmp = ip_map_lookup(class,addr); 221 if (ipmp) { 222 err = ip_map_update(ipmp, 223 container_of(dom, struct unix_domain, h), 224 expiry); 225 } else 226 err = -ENOMEM; 227 228 if (dom) 229 auth_domain_put(dom); 230 231 cache_flush(); 232 return err; 233 } 234 235 static int ip_map_show(struct seq_file *m, 236 struct cache_detail *cd, 237 struct cache_head *h) 238 { 239 struct ip_map *im; 240 struct in_addr addr; 241 char *dom = "-no-domain-"; 242 243 if (h == NULL) { 244 seq_puts(m, "#class IP domain\n"); 245 return 0; 246 } 247 im = container_of(h, struct ip_map, h); 248 /* class addr domain */ 249 addr = im->m_addr; 250 251 if (test_bit(CACHE_VALID, &h->flags) && 252 !test_bit(CACHE_NEGATIVE, &h->flags)) 253 dom = im->m_client->h.name; 254 255 seq_printf(m, "%s %d.%d.%d.%d %s\n", 256 im->m_class, 257 ntohl(addr.s_addr) >> 24 & 0xff, 258 ntohl(addr.s_addr) >> 16 & 0xff, 259 ntohl(addr.s_addr) >> 8 & 0xff, 260 ntohl(addr.s_addr) >> 0 & 0xff, 261 dom 262 ); 263 return 0; 264 } 265 266 267 struct cache_detail ip_map_cache = { 268 .owner = THIS_MODULE, 269 .hash_size = IP_HASHMAX, 270 .hash_table = ip_table, 271 .name = "auth.unix.ip", 272 .cache_put = ip_map_put, 273 .cache_request = ip_map_request, 274 .cache_parse = ip_map_parse, 275 .cache_show = ip_map_show, 276 .match = ip_map_match, 277 .init = ip_map_init, 278 .update = update, 279 .alloc = ip_map_alloc, 280 }; 281 282 static struct ip_map *ip_map_lookup(char *class, struct in_addr addr) 283 { 284 struct ip_map ip; 285 struct cache_head *ch; 286 287 strcpy(ip.m_class, class); 288 ip.m_addr = addr; 289 ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h, 290 hash_str(class, IP_HASHBITS) ^ 291 hash_ip(addr.s_addr)); 292 293 if (ch) 294 return container_of(ch, struct ip_map, h); 295 else 296 return NULL; 297 } 298 299 static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry) 300 { 301 struct ip_map ip; 302 struct cache_head *ch; 303 304 ip.m_client = udom; 305 ip.h.flags = 0; 306 if (!udom) 307 set_bit(CACHE_NEGATIVE, &ip.h.flags); 308 else { 309 ip.m_add_change = udom->addr_changes; 310 /* if this is from the legacy set_client system call, 311 * we need m_add_change to be one higher 312 */ 313 if (expiry == NEVER) 314 ip.m_add_change++; 315 } 316 ip.h.expiry_time = expiry; 317 ch = sunrpc_cache_update(&ip_map_cache, 318 &ip.h, &ipm->h, 319 hash_str(ipm->m_class, IP_HASHBITS) ^ 320 hash_ip(ipm->m_addr.s_addr)); 321 if (!ch) 322 return -ENOMEM; 323 cache_put(ch, &ip_map_cache); 324 return 0; 325 } 326 327 int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom) 328 { 329 struct unix_domain *udom; 330 struct ip_map *ipmp; 331 332 if (dom->flavour != &svcauth_unix) 333 return -EINVAL; 334 udom = container_of(dom, struct unix_domain, h); 335 ipmp = ip_map_lookup("nfsd", addr); 336 337 if (ipmp) 338 return ip_map_update(ipmp, udom, NEVER); 339 else 340 return -ENOMEM; 341 } 342 343 int auth_unix_forget_old(struct auth_domain *dom) 344 { 345 struct unix_domain *udom; 346 347 if (dom->flavour != &svcauth_unix) 348 return -EINVAL; 349 udom = container_of(dom, struct unix_domain, h); 350 udom->addr_changes++; 351 return 0; 352 } 353 354 struct auth_domain *auth_unix_lookup(struct in_addr addr) 355 { 356 struct ip_map *ipm; 357 struct auth_domain *rv; 358 359 ipm = ip_map_lookup("nfsd", addr); 360 361 if (!ipm) 362 return NULL; 363 if (cache_check(&ip_map_cache, &ipm->h, NULL)) 364 return NULL; 365 366 if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) { 367 if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0) 368 auth_domain_put(&ipm->m_client->h); 369 rv = NULL; 370 } else { 371 rv = &ipm->m_client->h; 372 kref_get(&rv->ref); 373 } 374 cache_put(&ipm->h, &ip_map_cache); 375 return rv; 376 } 377 378 void svcauth_unix_purge(void) 379 { 380 cache_purge(&ip_map_cache); 381 } 382 383 static inline struct ip_map * 384 ip_map_cached_get(struct svc_rqst *rqstp) 385 { 386 struct ip_map *ipm = rqstp->rq_sock->sk_info_authunix; 387 if (ipm != NULL) { 388 if (!cache_valid(&ipm->h)) { 389 /* 390 * The entry has been invalidated since it was 391 * remembered, e.g. by a second mount from the 392 * same IP address. 393 */ 394 rqstp->rq_sock->sk_info_authunix = NULL; 395 cache_put(&ipm->h, &ip_map_cache); 396 return NULL; 397 } 398 cache_get(&ipm->h); 399 } 400 return ipm; 401 } 402 403 static inline void 404 ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) 405 { 406 struct svc_sock *svsk = rqstp->rq_sock; 407 408 if (svsk->sk_sock->type == SOCK_STREAM && svsk->sk_info_authunix == NULL) 409 svsk->sk_info_authunix = ipm; /* newly cached, keep the reference */ 410 else 411 cache_put(&ipm->h, &ip_map_cache); 412 } 413 414 void 415 svcauth_unix_info_release(void *info) 416 { 417 struct ip_map *ipm = info; 418 cache_put(&ipm->h, &ip_map_cache); 419 } 420 421 static int 422 svcauth_unix_set_client(struct svc_rqst *rqstp) 423 { 424 struct ip_map *ipm; 425 426 rqstp->rq_client = NULL; 427 if (rqstp->rq_proc == 0) 428 return SVC_OK; 429 430 ipm = ip_map_cached_get(rqstp); 431 if (ipm == NULL) 432 ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, 433 rqstp->rq_addr.sin_addr); 434 435 if (ipm == NULL) 436 return SVC_DENIED; 437 438 switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) { 439 default: 440 BUG(); 441 case -EAGAIN: 442 case -ETIMEDOUT: 443 return SVC_DROP; 444 case -ENOENT: 445 return SVC_DENIED; 446 case 0: 447 rqstp->rq_client = &ipm->m_client->h; 448 kref_get(&rqstp->rq_client->ref); 449 ip_map_cached_put(rqstp, ipm); 450 break; 451 } 452 return SVC_OK; 453 } 454 455 static int 456 svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) 457 { 458 struct kvec *argv = &rqstp->rq_arg.head[0]; 459 struct kvec *resv = &rqstp->rq_res.head[0]; 460 struct svc_cred *cred = &rqstp->rq_cred; 461 462 cred->cr_group_info = NULL; 463 rqstp->rq_client = NULL; 464 465 if (argv->iov_len < 3*4) 466 return SVC_GARBAGE; 467 468 if (svc_getu32(argv) != 0) { 469 dprintk("svc: bad null cred\n"); 470 *authp = rpc_autherr_badcred; 471 return SVC_DENIED; 472 } 473 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 474 dprintk("svc: bad null verf\n"); 475 *authp = rpc_autherr_badverf; 476 return SVC_DENIED; 477 } 478 479 /* Signal that mapping to nobody uid/gid is required */ 480 cred->cr_uid = (uid_t) -1; 481 cred->cr_gid = (gid_t) -1; 482 cred->cr_group_info = groups_alloc(0); 483 if (cred->cr_group_info == NULL) 484 return SVC_DROP; /* kmalloc failure - client must retry */ 485 486 /* Put NULL verifier */ 487 svc_putnl(resv, RPC_AUTH_NULL); 488 svc_putnl(resv, 0); 489 490 return SVC_OK; 491 } 492 493 static int 494 svcauth_null_release(struct svc_rqst *rqstp) 495 { 496 if (rqstp->rq_client) 497 auth_domain_put(rqstp->rq_client); 498 rqstp->rq_client = NULL; 499 if (rqstp->rq_cred.cr_group_info) 500 put_group_info(rqstp->rq_cred.cr_group_info); 501 rqstp->rq_cred.cr_group_info = NULL; 502 503 return 0; /* don't drop */ 504 } 505 506 507 struct auth_ops svcauth_null = { 508 .name = "null", 509 .owner = THIS_MODULE, 510 .flavour = RPC_AUTH_NULL, 511 .accept = svcauth_null_accept, 512 .release = svcauth_null_release, 513 .set_client = svcauth_unix_set_client, 514 }; 515 516 517 static int 518 svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) 519 { 520 struct kvec *argv = &rqstp->rq_arg.head[0]; 521 struct kvec *resv = &rqstp->rq_res.head[0]; 522 struct svc_cred *cred = &rqstp->rq_cred; 523 u32 slen, i; 524 int len = argv->iov_len; 525 526 cred->cr_group_info = NULL; 527 rqstp->rq_client = NULL; 528 529 if ((len -= 3*4) < 0) 530 return SVC_GARBAGE; 531 532 svc_getu32(argv); /* length */ 533 svc_getu32(argv); /* time stamp */ 534 slen = XDR_QUADLEN(svc_getnl(argv)); /* machname length */ 535 if (slen > 64 || (len -= (slen + 3)*4) < 0) 536 goto badcred; 537 argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ 538 argv->iov_len -= slen*4; 539 540 cred->cr_uid = svc_getnl(argv); /* uid */ 541 cred->cr_gid = svc_getnl(argv); /* gid */ 542 slen = svc_getnl(argv); /* gids length */ 543 if (slen > 16 || (len -= (slen + 2)*4) < 0) 544 goto badcred; 545 cred->cr_group_info = groups_alloc(slen); 546 if (cred->cr_group_info == NULL) 547 return SVC_DROP; 548 for (i = 0; i < slen; i++) 549 GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); 550 551 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 552 *authp = rpc_autherr_badverf; 553 return SVC_DENIED; 554 } 555 556 /* Put NULL verifier */ 557 svc_putnl(resv, RPC_AUTH_NULL); 558 svc_putnl(resv, 0); 559 560 return SVC_OK; 561 562 badcred: 563 *authp = rpc_autherr_badcred; 564 return SVC_DENIED; 565 } 566 567 static int 568 svcauth_unix_release(struct svc_rqst *rqstp) 569 { 570 /* Verifier (such as it is) is already in place. 571 */ 572 if (rqstp->rq_client) 573 auth_domain_put(rqstp->rq_client); 574 rqstp->rq_client = NULL; 575 if (rqstp->rq_cred.cr_group_info) 576 put_group_info(rqstp->rq_cred.cr_group_info); 577 rqstp->rq_cred.cr_group_info = NULL; 578 579 return 0; 580 } 581 582 583 struct auth_ops svcauth_unix = { 584 .name = "unix", 585 .owner = THIS_MODULE, 586 .flavour = RPC_AUTH_UNIX, 587 .accept = svcauth_unix_accept, 588 .release = svcauth_unix_release, 589 .domain_release = svcauth_unix_domain_release, 590 .set_client = svcauth_unix_set_client, 591 }; 592 593