1 /*- 2 * Copyright (c) 2009 Rick Macklem, University of Guelph 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/errno.h> 33 #include <sys/linker.h> 34 #include <sys/module.h> 35 #include <sys/mount.h> 36 #include <sys/socket.h> 37 #include <sys/socketvar.h> 38 #include <sys/stat.h> 39 #include <sys/time.h> 40 #include <sys/ucred.h> 41 #include <sys/vnode.h> 42 #include <sys/wait.h> 43 44 #include <nfs/nfssvc.h> 45 46 #include <rpc/rpc.h> 47 #include <rpc/rpc_com.h> 48 49 #include <fs/nfs/rpcv2.h> 50 #include <fs/nfs/nfsproto.h> 51 #include <fs/nfs/nfskpiport.h> 52 #include <fs/nfs/nfs.h> 53 54 #include <ctype.h> 55 #include <err.h> 56 #include <grp.h> 57 #include <netdb.h> 58 #include <pwd.h> 59 #include <signal.h> 60 #include <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #include <syslog.h> 64 #include <unistd.h> 65 66 /* 67 * This program loads the password and group databases into the kernel 68 * for NFS V4. 69 */ 70 71 static void cleanup_term(int); 72 static void usage(void); 73 static void nfsuserdsrv(struct svc_req *, SVCXPRT *); 74 static bool_t xdr_getid(XDR *, caddr_t); 75 static bool_t xdr_getname(XDR *, caddr_t); 76 static bool_t xdr_retval(XDR *, caddr_t); 77 78 #ifndef _PATH_NFSUSERDSOCK 79 #define _PATH_NFSUSERDSOCK "/var/run/nfsuserd.sock" 80 #endif 81 #define MAXNAME 1024 82 #define MAXNFSUSERD 20 83 #define DEFNFSUSERD 4 84 #define MAXUSERMAX 100000 85 #define MINUSERMAX 10 86 #define DEFUSERMAX 200 87 #define DEFUSERTIMEOUT (1 * 60) 88 struct info { 89 long id; 90 long retval; 91 char name[MAXNAME + 1]; 92 }; 93 94 u_char *dnsname = "default.domain"; 95 u_char *defaultuser = "nobody"; 96 uid_t defaultuid = 65534; 97 u_char *defaultgroup = "nogroup"; 98 gid_t defaultgid = 65533; 99 int verbose = 0, im_a_slave = 0, nfsuserdcnt = -1, forcestart = 0; 100 int use_udpsock = 0; 101 int defusertimeout = DEFUSERTIMEOUT, manage_gids = 0; 102 pid_t slaves[MAXNFSUSERD]; 103 104 int 105 main(int argc, char *argv[]) 106 { 107 int i, j; 108 int error, fnd_dup, len, mustfreeai = 0, start_uidpos; 109 struct nfsd_idargs nid; 110 struct passwd *pwd; 111 struct group *grp; 112 int oldmask, one = 1, sock; 113 SVCXPRT *udptransp; 114 u_short portnum; 115 SVCXPRT *xprt; 116 sigset_t signew; 117 char hostname[MAXHOSTNAMELEN + 1], *cp; 118 struct addrinfo *aip, hints; 119 static uid_t check_dups[MAXUSERMAX]; 120 gid_t grps[NGROUPS]; 121 int ngroup; 122 struct sockaddr_un sun; 123 124 if (modfind("nfscommon") < 0) { 125 /* Not present in kernel, try loading it */ 126 if (kldload("nfscommon") < 0 || 127 modfind("nfscommon") < 0) 128 errx(1, "Experimental nfs subsystem is not available"); 129 } 130 131 /* 132 * First, figure out what our domain name and Kerberos Realm 133 * seem to be. Command line args may override these later. 134 */ 135 if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { 136 if ((cp = strchr(hostname, '.')) != NULL && 137 *(cp + 1) != '\0') { 138 dnsname = cp + 1; 139 } else { 140 memset((void *)&hints, 0, sizeof (hints)); 141 hints.ai_flags = AI_CANONNAME; 142 error = getaddrinfo(hostname, NULL, &hints, &aip); 143 if (error == 0) { 144 if (aip->ai_canonname != NULL && 145 (cp = strchr(aip->ai_canonname, '.')) != NULL 146 && *(cp + 1) != '\0') { 147 dnsname = cp + 1; 148 mustfreeai = 1; 149 } else { 150 freeaddrinfo(aip); 151 } 152 } 153 } 154 } 155 nid.nid_usermax = DEFUSERMAX; 156 nid.nid_usertimeout = defusertimeout; 157 158 argc--; 159 argv++; 160 while (argc >= 1) { 161 if (!strcmp(*argv, "-domain")) { 162 if (argc == 1) 163 usage(); 164 argc--; 165 argv++; 166 strncpy(hostname, *argv, MAXHOSTNAMELEN); 167 hostname[MAXHOSTNAMELEN] = '\0'; 168 dnsname = hostname; 169 } else if (!strcmp(*argv, "-verbose")) { 170 verbose = 1; 171 } else if (!strcmp(*argv, "-force")) { 172 forcestart = 1; 173 } else if (!strcmp(*argv, "-manage-gids")) { 174 manage_gids = 1; 175 } else if (!strcmp(*argv, "-use-udpsock")) { 176 use_udpsock = 1; 177 } else if (!strcmp(*argv, "-usermax")) { 178 if (argc == 1) 179 usage(); 180 argc--; 181 argv++; 182 i = atoi(*argv); 183 if (i < MINUSERMAX || i > MAXUSERMAX) { 184 fprintf(stderr, 185 "usermax %d out of range %d<->%d\n", i, 186 MINUSERMAX, MAXUSERMAX); 187 usage(); 188 } 189 nid.nid_usermax = i; 190 } else if (!strcmp(*argv, "-usertimeout")) { 191 if (argc == 1) 192 usage(); 193 argc--; 194 argv++; 195 i = atoi(*argv); 196 if (i < 0 || i > 100000) { 197 fprintf(stderr, 198 "usertimeout %d out of range 0<->100000\n", 199 i); 200 usage(); 201 } 202 nid.nid_usertimeout = defusertimeout = i * 60; 203 } else if (nfsuserdcnt == -1) { 204 nfsuserdcnt = atoi(*argv); 205 if (nfsuserdcnt < 1) 206 usage(); 207 if (nfsuserdcnt > MAXNFSUSERD) { 208 warnx("nfsuserd count %d; reset to %d", 209 nfsuserdcnt, DEFNFSUSERD); 210 nfsuserdcnt = DEFNFSUSERD; 211 } 212 } else { 213 usage(); 214 } 215 argc--; 216 argv++; 217 } 218 if (nfsuserdcnt < 1) 219 nfsuserdcnt = DEFNFSUSERD; 220 if (use_udpsock == 0) 221 /* For AF_LOCAL socket, only allow one server daemon. */ 222 nfsuserdcnt = 1; 223 224 /* 225 * Strip off leading and trailing '.'s in domain name and map 226 * alphabetics to lower case. 227 */ 228 while (*dnsname == '.') 229 dnsname++; 230 if (*dnsname == '\0') 231 errx(1, "Domain name all '.'"); 232 len = strlen(dnsname); 233 cp = dnsname + len - 1; 234 while (*cp == '.') { 235 *cp = '\0'; 236 len--; 237 cp--; 238 } 239 for (i = 0; i < len; i++) { 240 if (!isascii(dnsname[i])) 241 errx(1, "Domain name has non-ascii char"); 242 if (isupper(dnsname[i])) 243 dnsname[i] = tolower(dnsname[i]); 244 } 245 246 /* 247 * If the nfsuserd died off ungracefully, this is necessary to 248 * get them to start again. 249 */ 250 if (forcestart && nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) 251 errx(1, "Can't do nfssvc() to delete the port"); 252 253 if (verbose) 254 fprintf(stderr, 255 "nfsuserd: domain=%s usermax=%d usertimeout=%d\n", 256 dnsname, nid.nid_usermax, nid.nid_usertimeout); 257 258 for (i = 0; i < nfsuserdcnt; i++) 259 slaves[i] = (pid_t)-1; 260 261 if (use_udpsock != 0) { 262 /* 263 * Set up the service port to accept requests via UDP from 264 * localhost (127.0.0.1). 265 */ 266 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 267 err(1, "cannot create udp socket"); 268 269 /* 270 * Not sure what this does, so I'll leave it here for now. 271 */ 272 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 273 274 if ((udptransp = svcudp_create(sock)) == NULL) 275 err(1, "Can't set up socket"); 276 277 /* 278 * By not specifying a protocol, it is linked into the 279 * dispatch queue, but not registered with portmapper, 280 * which is just what I want. 281 */ 282 if (!svc_register(udptransp, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, 283 nfsuserdsrv, 0)) 284 err(1, "Can't register nfsuserd"); 285 286 /* 287 * Tell the kernel what my port# is. 288 */ 289 portnum = htons(udptransp->xp_port); 290 #ifdef DEBUG 291 printf("portnum=0x%x\n", portnum); 292 #else 293 if (nfssvc(NFSSVC_NFSUSERDPORT, (caddr_t)&portnum) < 0) { 294 if (errno == EPERM) 295 fprintf(stderr, "Can't start nfsuserd when" 296 " already running\nIf not running," 297 " use the -force option.\n"); 298 else 299 fprintf(stderr, 300 "Can't do nfssvc() to add socket\n"); 301 exit(1); 302 } 303 #endif 304 } else { 305 /* Use the AF_LOCAL socket. */ 306 memset(&sun, 0, sizeof sun); 307 sun.sun_family = AF_LOCAL; 308 unlink(_PATH_NFSUSERDSOCK); 309 strcpy(sun.sun_path, _PATH_NFSUSERDSOCK); 310 sun.sun_len = SUN_LEN(&sun); 311 sock = socket(AF_LOCAL, SOCK_STREAM, 0); 312 if (sock < 0) 313 err(1, "Can't create local nfsuserd socket"); 314 oldmask = umask(S_IXUSR | S_IRWXG | S_IRWXO); 315 if (bind(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) 316 err(1, "Can't bind local nfsuserd socket"); 317 umask(oldmask); 318 if (listen(sock, SOMAXCONN) < 0) 319 err(1, "Can't listen on local nfsuserd socket"); 320 xprt = svc_vc_create(sock, RPC_MAXDATASIZE, RPC_MAXDATASIZE); 321 if (xprt == NULL) 322 err(1, 323 "Can't create transport for local nfsuserd socket"); 324 if (!svc_reg(xprt, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, 325 nfsuserdsrv, NULL)) 326 err(1, 327 "Can't register service for local nfsuserd socket"); 328 329 /* 330 * Tell the kernel what the socket's path is. 331 */ 332 #ifdef DEBUG 333 printf("sockpath=%s\n", _PATH_NFSUSERDSOCK); 334 #else 335 if (nfssvc(NFSSVC_NFSUSERDPORT | NFSSVC_NEWSTRUCT, 336 _PATH_NFSUSERDSOCK) < 0) { 337 if (errno == EPERM) 338 fprintf(stderr, "Can't start nfsuserd when" 339 " already running\nIf not running," 340 " use the -force option.\n"); 341 else 342 fprintf(stderr, 343 "Can't do nfssvc() to add socket\n"); 344 exit(1); 345 } 346 #endif 347 } 348 349 pwd = getpwnam(defaultuser); 350 if (pwd) 351 nid.nid_uid = pwd->pw_uid; 352 else 353 nid.nid_uid = defaultuid; 354 grp = getgrnam(defaultgroup); 355 if (grp) 356 nid.nid_gid = grp->gr_gid; 357 else 358 nid.nid_gid = defaultgid; 359 nid.nid_name = dnsname; 360 nid.nid_namelen = strlen(nid.nid_name); 361 nid.nid_ngroup = 0; 362 nid.nid_grps = NULL; 363 nid.nid_flag = NFSID_INITIALIZE; 364 #ifdef DEBUG 365 printf("Initialize uid=%d gid=%d dns=%s\n", nid.nid_uid, nid.nid_gid, 366 nid.nid_name); 367 #else 368 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 369 if (error) 370 errx(1, "Can't initialize nfs user/groups"); 371 #endif 372 373 i = 0; 374 /* 375 * Loop around adding all groups. 376 */ 377 setgrent(); 378 while (i < nid.nid_usermax && (grp = getgrent())) { 379 nid.nid_gid = grp->gr_gid; 380 nid.nid_name = grp->gr_name; 381 nid.nid_namelen = strlen(grp->gr_name); 382 nid.nid_ngroup = 0; 383 nid.nid_grps = NULL; 384 nid.nid_flag = NFSID_ADDGID; 385 #ifdef DEBUG 386 printf("add gid=%d name=%s\n", nid.nid_gid, nid.nid_name); 387 #else 388 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 389 if (error) 390 errx(1, "Can't add group %s", grp->gr_name); 391 #endif 392 i++; 393 } 394 395 /* 396 * Loop around adding all users. 397 */ 398 start_uidpos = i; 399 setpwent(); 400 while (i < nid.nid_usermax && (pwd = getpwent())) { 401 fnd_dup = 0; 402 /* 403 * Yes, this is inefficient, but it is only done once when 404 * the daemon is started and will run in a fraction of a second 405 * for nid_usermax at 10000. If nid_usermax is cranked up to 406 * 100000, it will take several seconds, depending on the CPU. 407 */ 408 for (j = 0; j < (i - start_uidpos); j++) 409 if (check_dups[j] == pwd->pw_uid) { 410 /* Found another entry for uid, so skip it */ 411 fnd_dup = 1; 412 break; 413 } 414 if (fnd_dup != 0) 415 continue; 416 check_dups[i - start_uidpos] = pwd->pw_uid; 417 nid.nid_uid = pwd->pw_uid; 418 nid.nid_name = pwd->pw_name; 419 nid.nid_namelen = strlen(pwd->pw_name); 420 if (manage_gids != 0) { 421 /* Get the group list for this user. */ 422 ngroup = NGROUPS; 423 if (getgrouplist(pwd->pw_name, pwd->pw_gid, grps, 424 &ngroup) < 0) 425 syslog(LOG_ERR, "Group list too small"); 426 nid.nid_ngroup = ngroup; 427 nid.nid_grps = grps; 428 } else { 429 nid.nid_ngroup = 0; 430 nid.nid_grps = NULL; 431 } 432 nid.nid_flag = NFSID_ADDUID; 433 #ifdef DEBUG 434 printf("add uid=%d name=%s\n", nid.nid_uid, nid.nid_name); 435 #else 436 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 437 if (error) 438 errx(1, "Can't add user %s", pwd->pw_name); 439 #endif 440 i++; 441 } 442 443 /* 444 * I should feel guilty for not calling this for all the above exit() 445 * upon error cases, but I don't. 446 */ 447 if (mustfreeai) 448 freeaddrinfo(aip); 449 450 #ifdef DEBUG 451 exit(0); 452 #endif 453 /* 454 * Temporarily block SIGUSR1 and SIGCHLD, so slaves[] can't 455 * end up bogus. 456 */ 457 sigemptyset(&signew); 458 sigaddset(&signew, SIGUSR1); 459 sigaddset(&signew, SIGCHLD); 460 sigprocmask(SIG_BLOCK, &signew, NULL); 461 462 daemon(0, 0); 463 (void)signal(SIGHUP, SIG_IGN); 464 (void)signal(SIGINT, SIG_IGN); 465 (void)signal(SIGQUIT, SIG_IGN); 466 (void)signal(SIGTERM, SIG_IGN); 467 (void)signal(SIGUSR1, cleanup_term); 468 (void)signal(SIGCHLD, cleanup_term); 469 470 openlog("nfsuserd:", LOG_PID, LOG_DAEMON); 471 472 /* 473 * Fork off the slave daemons that do the work. All the master 474 * does is kill them off and cleanup. 475 */ 476 for (i = 0; i < nfsuserdcnt; i++) { 477 slaves[i] = fork(); 478 if (slaves[i] == 0) { 479 im_a_slave = 1; 480 setproctitle("slave"); 481 sigemptyset(&signew); 482 sigaddset(&signew, SIGUSR1); 483 sigprocmask(SIG_UNBLOCK, &signew, NULL); 484 485 /* 486 * and away we go. 487 */ 488 svc_run(); 489 syslog(LOG_ERR, "nfsuserd died: %m"); 490 exit(1); 491 } else if (slaves[i] < 0) { 492 syslog(LOG_ERR, "fork: %m"); 493 } 494 } 495 496 /* 497 * Just wait for SIGUSR1 or a child to die and then... 498 * As the Governor of California would say, "Terminate them". 499 */ 500 setproctitle("master"); 501 sigemptyset(&signew); 502 while (1) 503 sigsuspend(&signew); 504 } 505 506 /* 507 * The nfsuserd rpc service 508 */ 509 static void 510 nfsuserdsrv(struct svc_req *rqstp, SVCXPRT *transp) 511 { 512 struct passwd *pwd; 513 struct group *grp; 514 int error; 515 u_short sport; 516 struct info info; 517 struct nfsd_idargs nid; 518 u_int32_t saddr; 519 gid_t grps[NGROUPS]; 520 int ngroup; 521 522 if (use_udpsock != 0) { 523 /* 524 * Only handle requests from 127.0.0.1 on a reserved port 525 * number. (Since a reserved port # at localhost implies a 526 * client with local root, there won't be a security breach. 527 * This is about the only case I can think of where a reserved 528 * port # means something.) 529 */ 530 sport = ntohs(transp->xp_raddr.sin_port); 531 saddr = ntohl(transp->xp_raddr.sin_addr.s_addr); 532 if ((rqstp->rq_proc != NULLPROC && sport >= IPPORT_RESERVED) || 533 saddr != 0x7f000001) { 534 syslog(LOG_ERR, "req from ip=0x%x port=%d, consider" 535 " using an AF_LOCAL socket\n", saddr, sport); 536 svcerr_weakauth(transp); 537 return; 538 } 539 } 540 541 switch (rqstp->rq_proc) { 542 case NULLPROC: 543 if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 544 syslog(LOG_ERR, "Can't send reply"); 545 return; 546 case RPCNFSUSERD_GETUID: 547 if (!svc_getargs(transp, (xdrproc_t)xdr_getid, 548 (caddr_t)&info)) { 549 svcerr_decode(transp); 550 return; 551 } 552 pwd = getpwuid((uid_t)info.id); 553 info.retval = 0; 554 if (pwd != NULL) { 555 nid.nid_usertimeout = defusertimeout; 556 nid.nid_uid = pwd->pw_uid; 557 nid.nid_name = pwd->pw_name; 558 if (manage_gids != 0) { 559 /* Get the group list for this user. */ 560 ngroup = NGROUPS; 561 if (getgrouplist(pwd->pw_name, pwd->pw_gid, 562 grps, &ngroup) < 0) 563 syslog(LOG_ERR, "Group list too small"); 564 nid.nid_ngroup = ngroup; 565 nid.nid_grps = grps; 566 } else { 567 nid.nid_ngroup = 0; 568 nid.nid_grps = NULL; 569 } 570 } else { 571 nid.nid_usertimeout = 5; 572 nid.nid_uid = (uid_t)info.id; 573 nid.nid_name = defaultuser; 574 nid.nid_ngroup = 0; 575 nid.nid_grps = NULL; 576 } 577 nid.nid_namelen = strlen(nid.nid_name); 578 nid.nid_flag = NFSID_ADDUID; 579 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 580 if (error) { 581 info.retval = error; 582 syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name); 583 } else if (verbose) { 584 syslog(LOG_ERR,"Added uid=%d name=%s\n", 585 nid.nid_uid, nid.nid_name); 586 } 587 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 588 (caddr_t)&info)) 589 syslog(LOG_ERR, "Can't send reply"); 590 return; 591 case RPCNFSUSERD_GETGID: 592 if (!svc_getargs(transp, (xdrproc_t)xdr_getid, 593 (caddr_t)&info)) { 594 svcerr_decode(transp); 595 return; 596 } 597 grp = getgrgid((gid_t)info.id); 598 info.retval = 0; 599 if (grp != NULL) { 600 nid.nid_usertimeout = defusertimeout; 601 nid.nid_gid = grp->gr_gid; 602 nid.nid_name = grp->gr_name; 603 } else { 604 nid.nid_usertimeout = 5; 605 nid.nid_gid = (gid_t)info.id; 606 nid.nid_name = defaultgroup; 607 } 608 nid.nid_namelen = strlen(nid.nid_name); 609 nid.nid_ngroup = 0; 610 nid.nid_grps = NULL; 611 nid.nid_flag = NFSID_ADDGID; 612 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 613 if (error) { 614 info.retval = error; 615 syslog(LOG_ERR, "Can't add group %s\n", 616 grp->gr_name); 617 } else if (verbose) { 618 syslog(LOG_ERR,"Added gid=%d name=%s\n", 619 nid.nid_gid, nid.nid_name); 620 } 621 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 622 (caddr_t)&info)) 623 syslog(LOG_ERR, "Can't send reply"); 624 return; 625 case RPCNFSUSERD_GETUSER: 626 if (!svc_getargs(transp, (xdrproc_t)xdr_getname, 627 (caddr_t)&info)) { 628 svcerr_decode(transp); 629 return; 630 } 631 pwd = getpwnam(info.name); 632 info.retval = 0; 633 if (pwd != NULL) { 634 nid.nid_usertimeout = defusertimeout; 635 nid.nid_uid = pwd->pw_uid; 636 nid.nid_name = pwd->pw_name; 637 } else { 638 nid.nid_usertimeout = 5; 639 nid.nid_uid = defaultuid; 640 nid.nid_name = info.name; 641 } 642 nid.nid_namelen = strlen(nid.nid_name); 643 nid.nid_ngroup = 0; 644 nid.nid_grps = NULL; 645 nid.nid_flag = NFSID_ADDUSERNAME; 646 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 647 if (error) { 648 info.retval = error; 649 syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name); 650 } else if (verbose) { 651 syslog(LOG_ERR,"Added uid=%d name=%s\n", 652 nid.nid_uid, nid.nid_name); 653 } 654 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 655 (caddr_t)&info)) 656 syslog(LOG_ERR, "Can't send reply"); 657 return; 658 case RPCNFSUSERD_GETGROUP: 659 if (!svc_getargs(transp, (xdrproc_t)xdr_getname, 660 (caddr_t)&info)) { 661 svcerr_decode(transp); 662 return; 663 } 664 grp = getgrnam(info.name); 665 info.retval = 0; 666 if (grp != NULL) { 667 nid.nid_usertimeout = defusertimeout; 668 nid.nid_gid = grp->gr_gid; 669 nid.nid_name = grp->gr_name; 670 } else { 671 nid.nid_usertimeout = 5; 672 nid.nid_gid = defaultgid; 673 nid.nid_name = info.name; 674 } 675 nid.nid_namelen = strlen(nid.nid_name); 676 nid.nid_ngroup = 0; 677 nid.nid_grps = NULL; 678 nid.nid_flag = NFSID_ADDGROUPNAME; 679 error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid); 680 if (error) { 681 info.retval = error; 682 syslog(LOG_ERR, "Can't add group %s\n", 683 grp->gr_name); 684 } else if (verbose) { 685 syslog(LOG_ERR,"Added gid=%d name=%s\n", 686 nid.nid_gid, nid.nid_name); 687 } 688 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 689 (caddr_t)&info)) 690 syslog(LOG_ERR, "Can't send reply"); 691 return; 692 default: 693 svcerr_noproc(transp); 694 return; 695 }; 696 } 697 698 /* 699 * Xdr routine to get an id number 700 */ 701 static bool_t 702 xdr_getid(XDR *xdrsp, caddr_t cp) 703 { 704 struct info *ifp = (struct info *)cp; 705 706 return (xdr_long(xdrsp, &ifp->id)); 707 } 708 709 /* 710 * Xdr routine to get a user name 711 */ 712 static bool_t 713 xdr_getname(XDR *xdrsp, caddr_t cp) 714 { 715 struct info *ifp = (struct info *)cp; 716 long len; 717 718 if (!xdr_long(xdrsp, &len)) 719 return (0); 720 if (len > MAXNAME) 721 return (0); 722 if (!xdr_opaque(xdrsp, ifp->name, len)) 723 return (0); 724 ifp->name[len] = '\0'; 725 return (1); 726 } 727 728 /* 729 * Xdr routine to return the value. 730 */ 731 static bool_t 732 xdr_retval(XDR *xdrsp, caddr_t cp) 733 { 734 struct info *ifp = (struct info *)cp; 735 long val; 736 737 val = ifp->retval; 738 return (xdr_long(xdrsp, &val)); 739 } 740 741 /* 742 * cleanup_term() called via SIGUSR1. 743 */ 744 static void 745 cleanup_term(int signo __unused) 746 { 747 int i, cnt; 748 749 if (im_a_slave) 750 exit(0); 751 752 /* 753 * Ok, so I'm the master. 754 * As the Governor of California might say, "Terminate them". 755 */ 756 cnt = 0; 757 for (i = 0; i < nfsuserdcnt; i++) { 758 if (slaves[i] != (pid_t)-1) { 759 cnt++; 760 kill(slaves[i], SIGUSR1); 761 } 762 } 763 764 /* 765 * and wait for them to die 766 */ 767 for (i = 0; i < cnt; i++) 768 wait3(NULL, 0, NULL); 769 770 /* 771 * Finally, get rid of the socket 772 */ 773 if (nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) { 774 syslog(LOG_ERR, "Can't do nfssvc() to delete the port\n"); 775 exit(1); 776 } 777 exit(0); 778 } 779 780 static void 781 usage(void) 782 { 783 784 errx(1, "usage: nfsuserd [-usermax cache_size] [-usertimeout minutes]" 785 " [-verbose] [-manage-gids] [-use-udpsock] [-domain domain_name]" 786 " [n]"); 787 } 788