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