1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <sys/ioccom.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <strings.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <stdarg.h> 37 #include <fcntl.h> 38 #include <wait.h> 39 #include <signal.h> 40 #include <libscf.h> 41 #include <limits.h> 42 #include <priv_utils.h> 43 #include <door.h> 44 #include <errno.h> 45 #include <syslog.h> 46 #include <pthread.h> 47 #include <time.h> 48 #include <libscf.h> 49 #include <zone.h> 50 #include <tzfile.h> 51 #include <libgen.h> 52 #include <pwd.h> 53 #include <grp.h> 54 55 #include <smbsrv/smb_door_svc.h> 56 #include <smbsrv/smb_ioctl.h> 57 #include <smbsrv/libsmb.h> 58 #include <smbsrv/libsmbns.h> 59 #include <smbsrv/libsmbrdr.h> 60 #include <smbsrv/libmlsvc.h> 61 62 #include "smbd.h" 63 64 #define DRV_DEVICE_PATH "/devices/pseudo/smbsrv@0:smbsrv" 65 #define SMB_CACHEDIR "/var/run/smb" 66 #define SMB_DBDIR "/var/smb" 67 68 extern void smb_netbios_name_reconfig(); 69 extern void smb_browser_config(); 70 71 static int smbd_daemonize_init(void); 72 static void smbd_daemonize_fini(int, int); 73 74 static int smbd_kernel_bind(void); 75 static void smbd_kernel_unbind(void); 76 static int smbd_already_running(void); 77 78 static int smbd_service_init(void); 79 static void smbd_service_fini(void); 80 81 static int smbd_setup_options(int argc, char *argv[]); 82 static void smbd_usage(FILE *fp); 83 static void smbd_report(const char *fmt, ...); 84 85 static void smbd_sig_handler(int sig); 86 87 static int smbd_localtime_init(void); 88 static void *smbd_localtime_monitor(void *arg); 89 90 extern time_t altzone; 91 92 static pthread_t localtime_thr; 93 94 static int smbd_refresh_init(void); 95 static void smbd_refresh_fini(void); 96 static void *smbd_refresh_monitor(void *); 97 static pthread_t refresh_thr; 98 static pthread_cond_t refresh_cond; 99 static pthread_mutex_t refresh_mutex; 100 101 static smbd_t smbd; 102 103 /* 104 * smbd user land daemon 105 * 106 * Use SMF error codes only on return or exit. 107 */ 108 int 109 main(int argc, char *argv[]) 110 { 111 struct sigaction act; 112 sigset_t set; 113 uid_t uid; 114 int pfd = -1; 115 116 smbd.s_pname = basename(argv[0]); 117 openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 118 119 if (smbd_setup_options(argc, argv) != 0) 120 return (SMF_EXIT_ERR_FATAL); 121 122 if ((uid = getuid()) != smbd.s_uid) { 123 smbd_report("user %d: %s", uid, strerror(EPERM)); 124 return (SMF_EXIT_ERR_FATAL); 125 } 126 127 if (getzoneid() != GLOBAL_ZONEID) { 128 smbd_report("non-global zones are not supported"); 129 return (SMF_EXIT_ERR_FATAL); 130 } 131 132 if (is_system_labeled()) { 133 smbd_report("Trusted Extensions not supported"); 134 return (SMF_EXIT_ERR_FATAL); 135 } 136 137 if (smbd_already_running()) 138 return (SMF_EXIT_OK); 139 140 (void) sigfillset(&set); 141 (void) sigdelset(&set, SIGABRT); 142 143 (void) sigfillset(&act.sa_mask); 144 act.sa_handler = smbd_sig_handler; 145 act.sa_flags = 0; 146 147 (void) sigaction(SIGTERM, &act, NULL); 148 (void) sigaction(SIGHUP, &act, NULL); 149 (void) sigaction(SIGINT, &act, NULL); 150 (void) sigaction(SIGPIPE, &act, NULL); 151 152 (void) sigdelset(&set, SIGTERM); 153 (void) sigdelset(&set, SIGHUP); 154 (void) sigdelset(&set, SIGINT); 155 (void) sigdelset(&set, SIGPIPE); 156 157 if (smbd.s_fg) { 158 (void) sigdelset(&set, SIGTSTP); 159 (void) sigdelset(&set, SIGTTIN); 160 (void) sigdelset(&set, SIGTTOU); 161 162 if (smbd_service_init() != 0) { 163 smbd_report("service initialization failed"); 164 exit(SMF_EXIT_ERR_FATAL); 165 } 166 } else { 167 /* 168 * "pfd" is a pipe descriptor -- any fatal errors 169 * during subsequent initialization of the child 170 * process should be written to this pipe and the 171 * parent will report this error as the exit status. 172 */ 173 pfd = smbd_daemonize_init(); 174 175 if (smbd_service_init() != 0) { 176 smbd_report("daemon initialization failed"); 177 exit(SMF_EXIT_ERR_FATAL); 178 } 179 180 smbd_daemonize_fini(pfd, SMF_EXIT_OK); 181 } 182 183 (void) atexit(smbd_service_fini); 184 185 while (!smbd.s_shutdown_flag) { 186 (void) sigsuspend(&set); 187 188 switch (smbd.s_sigval) { 189 case 0: 190 break; 191 192 case SIGPIPE: 193 break; 194 195 case SIGHUP: 196 /* Refresh config was triggered */ 197 if (smbd.s_fg) 198 smbd_report("reconfiguration requested"); 199 (void) pthread_cond_signal(&refresh_cond); 200 break; 201 202 default: 203 /* 204 * Typically SIGINT or SIGTERM. 205 */ 206 smbd.s_shutdown_flag = 1; 207 break; 208 } 209 210 smbd.s_sigval = 0; 211 } 212 213 smbd_service_fini(); 214 closelog(); 215 return (SMF_EXIT_OK); 216 } 217 218 /* 219 * This function will fork off a child process, 220 * from which only the child will return. 221 * 222 * Use SMF error codes only on exit. 223 */ 224 static int 225 smbd_daemonize_init(void) 226 { 227 int status, pfds[2]; 228 sigset_t set, oset; 229 pid_t pid; 230 int rc; 231 232 /* 233 * Reset privileges to the minimum set required. We continue 234 * to run as root to create and access files in /var. 235 */ 236 rc = __init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS, 237 smbd.s_uid, smbd.s_gid, 238 PRIV_NET_MAC_AWARE, PRIV_NET_PRIVADDR, PRIV_PROC_AUDIT, 239 PRIV_SYS_DEVICES, PRIV_SYS_SMB, NULL); 240 241 if (rc != 0) { 242 smbd_report("insufficient privileges"); 243 exit(SMF_EXIT_ERR_FATAL); 244 } 245 246 /* 247 * Block all signals prior to the fork and leave them blocked in the 248 * parent so we don't get in a situation where the parent gets SIGINT 249 * and returns non-zero exit status and the child is actually running. 250 * In the child, restore the signal mask once we've done our setsid(). 251 */ 252 (void) sigfillset(&set); 253 (void) sigdelset(&set, SIGABRT); 254 (void) sigprocmask(SIG_BLOCK, &set, &oset); 255 256 if (pipe(pfds) == -1) { 257 smbd_report("unable to create pipe"); 258 exit(SMF_EXIT_ERR_FATAL); 259 } 260 261 closelog(); 262 263 if ((pid = fork()) == -1) { 264 openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 265 smbd_report("unable to fork"); 266 closelog(); 267 exit(SMF_EXIT_ERR_FATAL); 268 } 269 270 /* 271 * If we're the parent process, wait for either the child to send us 272 * the appropriate exit status over the pipe or for the read to fail 273 * (presumably with 0 for EOF if our child terminated abnormally). 274 * If the read fails, exit with either the child's exit status if it 275 * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal. 276 */ 277 if (pid != 0) { 278 (void) close(pfds[1]); 279 280 if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 281 _exit(status); 282 283 if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 284 _exit(WEXITSTATUS(status)); 285 286 _exit(SMF_EXIT_ERR_FATAL); 287 } 288 289 openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 290 smbd.s_pid = getpid(); 291 (void) setsid(); 292 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 293 (void) chdir("/"); 294 (void) umask(022); 295 (void) close(pfds[0]); 296 297 return (pfds[1]); 298 } 299 300 static void 301 smbd_daemonize_fini(int fd, int exit_status) 302 { 303 /* 304 * Now that we're running, if a pipe fd was specified, write an exit 305 * status to it to indicate that our parent process can safely detach. 306 * Then proceed to loading the remaining non-built-in modules. 307 */ 308 if (fd >= 0) 309 (void) write(fd, &exit_status, sizeof (exit_status)); 310 311 (void) close(fd); 312 313 if ((fd = open("/dev/null", O_RDWR)) >= 0) { 314 (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 315 (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 316 (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 317 (void) close(fd); 318 } 319 320 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 321 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, NULL); 322 } 323 324 static int 325 smbd_service_init(void) 326 { 327 static char *dir[] = { 328 SMB_DBDIR, /* smbpasswd */ 329 SMB_CACHEDIR /* KRB credential cache */ 330 }; 331 332 int rc; 333 int ddns_enabled; 334 uint32_t mode; 335 char resource_domain[SMB_PI_MAX_DOMAIN]; 336 int i; 337 338 smbd.s_drv_fd = -1; 339 340 for (i = 0; i < (sizeof (dir)/sizeof (dir[0])); ++i) { 341 errno = 0; 342 343 if ((mkdir(dir[i], 0700) < 0) && (errno != EEXIST)) { 344 smbd_report("mkdir %s: %s", dir[i], strerror(errno)); 345 return (1); 346 } 347 } 348 349 /* 350 * Set KRB5CCNAME (for the SMB credential cache) in the environment. 351 */ 352 if (putenv("KRB5CCNAME=" SMB_CACHEDIR "/ccache") != 0) { 353 smbd_report("unable to set KRB5CCNAME"); 354 return (1); 355 } 356 357 (void) oem_language_set("english"); 358 359 if (!nt_builtin_init()) { 360 smbd_report("out of memory"); 361 return (1); 362 } 363 364 /* 365 * Need to load the configuration data prior to getting the 366 * interface information. 367 */ 368 if (smb_config_load() != 0) { 369 smbd_report("failed to load configuration data"); 370 return (1); 371 } 372 373 smb_resolver_init(); 374 (void) smb_nicmon_start(); 375 376 smbrdr_init(); 377 378 smb_netbios_start(); 379 if (smb_netlogon_init() != 0) { 380 smbd_report("netlogon initialization failed"); 381 return (1); 382 } 383 384 smb_config_rdlock(); 385 resource_domain[0] = '\0'; 386 (void) strlcpy(resource_domain, 387 smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); 388 (void) utf8_strupr(resource_domain); 389 smb_config_unlock(); 390 391 mode = smb_get_security_mode(); 392 393 if (mode == SMB_SECMODE_DOMAIN) 394 (void) locate_resource_pdc(resource_domain); 395 396 /* Get the ID map client handle */ 397 if ((rc = smb_idmap_start()) != 0) { 398 smbd_report("no idmap handle"); 399 return (rc); 400 } 401 402 if ((rc = nt_domain_init(resource_domain, mode)) != 0) { 403 if (rc == SMB_DOMAIN_NOMACHINE_SID) 404 smbd_report("No Security Identifier (SID) has been " 405 "generated for this system.\n" 406 "Check idmap service configuration."); 407 408 if (rc == SMB_DOMAIN_NODOMAIN_SID) { 409 /* Get the domain sid from domain controller */ 410 if ((rc = lsa_query_primary_domain_info()) != 0) 411 smbd_report("Failed to get the Security " 412 "Identifier (SID) of domain %s", 413 resource_domain); 414 } 415 return (rc); 416 } 417 418 if ((rc = mlsvc_init()) != 0) { 419 smbd_report("msrpc initialization failed"); 420 return (rc); 421 } 422 423 if (rc = smb_mlsvc_srv_start()) { 424 smbd_report("msrpc door initialization failed: %d", rc); 425 return (rc); 426 } 427 428 if (smb_lmshrd_srv_start() != 0) { 429 smbd_report("share initialization failed"); 430 } 431 432 /* XXX following will get removed */ 433 (void) smb_doorsrv_start(); 434 if ((rc = smb_door_srv_start()) != 0) 435 return (rc); 436 437 if ((rc = smbd_refresh_init()) != 0) 438 return (rc); 439 440 /* Call dyndns update - Just in case its configured to refresh DNS */ 441 smb_config_rdlock(); 442 ddns_enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); 443 smb_config_unlock(); 444 if (ddns_enabled) { 445 (void) dyndns_update(); 446 } 447 448 if ((rc = smbd_kernel_bind()) != 0) 449 smbd_report("kernel bind error: %s", strerror(errno)); 450 451 (void) smbd_localtime_init(); 452 453 return (lmshare_start()); 454 } 455 456 /* 457 * Close the kernel service and shutdown smbd services. 458 * This function is registered with atexit(): ensure that anything 459 * called from here is safe to be called multiple times. 460 */ 461 static void 462 smbd_service_fini(void) 463 { 464 nt_builtin_fini(); 465 smbd_refresh_fini(); 466 smbd_kernel_unbind(); 467 smb_door_srv_stop(); 468 smb_doorsrv_stop(); 469 smb_lmshrd_srv_stop(); 470 lmshare_stop(); 471 smb_mlsvc_srv_stop(); 472 smb_nicmon_stop(); 473 smb_resolver_close(); 474 smb_idmap_stop(); 475 } 476 477 /* 478 * smbd_refresh_init() 479 * 480 * SMB service refresh thread initialization. This thread waits for a 481 * refresh event and updates the daemon's view of the configuration 482 * before going back to sleep. 483 */ 484 static int 485 smbd_refresh_init() 486 { 487 pthread_attr_t tattr; 488 pthread_condattr_t cattr; 489 int rc; 490 491 (void) pthread_condattr_init(&cattr); 492 (void) pthread_cond_init(&refresh_cond, &cattr); 493 (void) pthread_condattr_destroy(&cattr); 494 495 (void) pthread_mutex_init(&refresh_mutex, NULL); 496 497 (void) pthread_attr_init(&tattr); 498 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 499 rc = pthread_create(&refresh_thr, &tattr, smbd_refresh_monitor, 0); 500 (void) pthread_attr_destroy(&tattr); 501 return (rc); 502 503 } 504 505 /* 506 * smbd_refresh_fini() 507 * 508 * Stop the refresh thread. 509 */ 510 static void 511 smbd_refresh_fini() 512 { 513 (void) pthread_cancel(refresh_thr); 514 515 (void) pthread_cond_destroy(&refresh_cond); 516 (void) pthread_mutex_destroy(&refresh_mutex); 517 } 518 519 /* 520 * smbd_refresh_monitor() 521 * 522 * Wait for a refresh event. When this thread wakes up, update the 523 * smbd configuration from the SMF config information then go back to 524 * wait for the next refresh. 525 */ 526 /*ARGSUSED*/ 527 static void * 528 smbd_refresh_monitor(void *arg) 529 { 530 int dummy = 0; 531 532 (void) pthread_mutex_lock(&refresh_mutex); 533 while (pthread_cond_wait(&refresh_cond, &refresh_mutex) == 0) { 534 /* 535 * We've been woken up by a refresh event so go do 536 * what is necessary. 537 */ 538 (void) smb_config_load(); 539 smb_nic_build_info(); 540 (void) smb_netbios_name_reconfig(); 541 (void) smb_browser_config(); 542 if (ioctl(smbd.s_drv_fd, SMB_IOC_CONFIG_REFRESH, &dummy) < 0) { 543 smbd_report("configuration update ioctl: %s", 544 strerror(errno)); 545 } 546 } 547 return (NULL); 548 } 549 550 551 /* 552 * If the door has already been opened by another process (non-zero pid 553 * in target), we assume that another smbd is already running. If there 554 * is a race here, it will be caught later when smbsrv is opened because 555 * only one process is allowed to open the device at a time. 556 */ 557 static int 558 smbd_already_running(void) 559 { 560 door_info_t info; 561 int door; 562 563 if ((door = open(SMBD_DOOR_NAME, O_RDONLY)) < 0) 564 return (0); 565 566 if (door_info(door, &info) < 0) 567 return (0); 568 569 if (info.di_target > 0) { 570 smbd_report("already running: pid %ld\n", info.di_target); 571 (void) close(door); 572 return (1); 573 } 574 575 (void) close(door); 576 return (0); 577 } 578 579 static int 580 smbd_kernel_bind(void) 581 { 582 if (smbd.s_drv_fd != -1) 583 (void) close(smbd.s_drv_fd); 584 585 if ((smbd.s_drv_fd = open(DRV_DEVICE_PATH, 0)) < 0) { 586 smbd.s_drv_fd = -1; 587 return (1); 588 } 589 return (0); 590 } 591 592 593 /* 594 * Initialization of the localtime thread. 595 * Returns 0 on success, an error number if thread creation fails. 596 */ 597 598 int 599 smbd_localtime_init(void) 600 { 601 pthread_attr_t tattr; 602 int rc; 603 604 (void) pthread_attr_init(&tattr); 605 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 606 rc = pthread_create(&localtime_thr, &tattr, smbd_localtime_monitor, 0); 607 (void) pthread_attr_destroy(&tattr); 608 return (rc); 609 } 610 611 /* 612 * Local time thread to kernel land. 613 * Send local gmtoff to kernel module one time at startup 614 * and each time it changes (up to twice a year). 615 * Local gmtoff is checked once every 15 minutes and 616 * since some timezones are aligned on half and qtr hour boundaries, 617 * once an hour would likely suffice. 618 */ 619 620 /*ARGSUSED*/ 621 static void * 622 smbd_localtime_monitor(void *arg) 623 { 624 struct tm local_tm; 625 time_t secs, gmtoff; 626 time_t last_gmtoff = -1; 627 int timeout; 628 629 for (;;) { 630 gmtoff = -altzone; 631 632 if ((last_gmtoff != gmtoff) && (smbd.s_drv_fd != -1)) { 633 if (ioctl(smbd.s_drv_fd, SMB_IOC_GMTOFF, &gmtoff) < 0) { 634 smbd_report("localtime ioctl: %s", 635 strerror(errno)); 636 } 637 } 638 639 /* 640 * Align the next iteration on a fifteen minute boundary. 641 */ 642 secs = time(0); 643 (void) localtime_r(&secs, &local_tm); 644 timeout = ((15 - (local_tm.tm_min % 15)) * SECSPERMIN); 645 (void) sleep(timeout); 646 647 last_gmtoff = gmtoff; 648 } 649 650 /*NOTREACHED*/ 651 return (NULL); 652 } 653 654 655 static void 656 smbd_kernel_unbind(void) 657 { 658 if (smbd.s_drv_fd != -1) { 659 (void) close(smbd.s_drv_fd); 660 smbd.s_drv_fd = -1; 661 } 662 } 663 664 static void 665 smbd_sig_handler(int sigval) 666 { 667 if (smbd.s_sigval == 0) 668 smbd.s_sigval = sigval; 669 } 670 671 /* 672 * Set up configuration options and parse the command line. 673 * This function will determine if we will run as a daemon 674 * or in the foreground. 675 * 676 * Failure to find a uid or gid results in using the default (0). 677 */ 678 static int 679 smbd_setup_options(int argc, char *argv[]) 680 { 681 struct passwd *pwd; 682 struct group *grp; 683 int c; 684 685 if ((pwd = getpwnam("root")) != NULL) 686 smbd.s_uid = pwd->pw_uid; 687 688 if ((grp = getgrnam("sys")) != NULL) 689 smbd.s_gid = grp->gr_gid; 690 691 smbd.s_fg = smb_get_fg_flag(); 692 693 while ((c = getopt(argc, argv, ":f")) != -1) { 694 switch (c) { 695 case 'f': 696 smbd.s_fg = 1; 697 break; 698 699 case ':': 700 case '?': 701 default: 702 smbd_usage(stderr); 703 return (-1); 704 } 705 } 706 707 return (0); 708 } 709 710 static void 711 smbd_usage(FILE *fp) 712 { 713 static char *help[] = { 714 "-f run program in foreground" 715 }; 716 717 int i; 718 719 (void) fprintf(fp, "Usage: %s [-f]\n", smbd.s_pname); 720 721 for (i = 0; i < sizeof (help)/sizeof (help[0]); ++i) 722 (void) fprintf(fp, " %s\n", help[i]); 723 } 724 725 static void 726 smbd_report(const char *fmt, ...) 727 { 728 char buf[128]; 729 va_list ap; 730 731 if (fmt == NULL) 732 return; 733 734 va_start(ap, fmt); 735 (void) vsnprintf(buf, 128, fmt, ap); 736 va_end(ap); 737 738 (void) fprintf(stderr, "smbd: %s\n", buf); 739 } 740 741 /* 742 * Enable libumem debugging by default on DEBUG builds. 743 */ 744 #ifdef DEBUG 745 /* LINTED - external libumem symbol */ 746 const char * 747 _umem_debug_init(void) 748 { 749 return ("default,verbose"); /* $UMEM_DEBUG setting */ 750 } 751 752 /* LINTED - external libumem symbol */ 753 const char * 754 _umem_logging_init(void) 755 { 756 return ("fail,contents"); /* $UMEM_LOGGING setting */ 757 } 758 #endif 759