1c5c4113dSnw141292 /* 2c5c4113dSnw141292 * CDDL HEADER START 3c5c4113dSnw141292 * 4c5c4113dSnw141292 * The contents of this file are subject to the terms of the 5c5c4113dSnw141292 * Common Development and Distribution License (the "License"). 6c5c4113dSnw141292 * You may not use this file except in compliance with the License. 7c5c4113dSnw141292 * 8c5c4113dSnw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c5c4113dSnw141292 * or http://www.opensolaris.org/os/licensing. 10c5c4113dSnw141292 * See the License for the specific language governing permissions 11c5c4113dSnw141292 * and limitations under the License. 12c5c4113dSnw141292 * 13c5c4113dSnw141292 * When distributing Covered Code, include this CDDL HEADER in each 14c5c4113dSnw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c5c4113dSnw141292 * If applicable, add the following below this CDDL HEADER, with the 16c5c4113dSnw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17c5c4113dSnw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18c5c4113dSnw141292 * 19c5c4113dSnw141292 * CDDL HEADER END 20c5c4113dSnw141292 */ 21c5c4113dSnw141292 /* 22*c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23c5c4113dSnw141292 */ 24c5c4113dSnw141292 25c5c4113dSnw141292 26c5c4113dSnw141292 /* 27c5c4113dSnw141292 * main() of idmapd(1M) 28c5c4113dSnw141292 */ 29c5c4113dSnw141292 30c5c4113dSnw141292 #include "idmapd.h" 3171590c90Snw141292 #include <atomic.h> 32c5c4113dSnw141292 #include <signal.h> 33c5c4113dSnw141292 #include <rpc/pmap_clnt.h> /* for pmap_unset */ 34c5c4113dSnw141292 #include <string.h> /* strcmp */ 35c5c4113dSnw141292 #include <unistd.h> /* setsid */ 36c5c4113dSnw141292 #include <sys/types.h> 37c5c4113dSnw141292 #include <memory.h> 38c5c4113dSnw141292 #include <stropts.h> 39c5c4113dSnw141292 #include <netconfig.h> 40c5c4113dSnw141292 #include <sys/resource.h> /* rlimit */ 41c5c4113dSnw141292 #include <rpcsvc/daemon_utils.h> /* DAEMON_UID and DAEMON_GID */ 42c5c4113dSnw141292 #include <priv_utils.h> /* privileges */ 43c5c4113dSnw141292 #include <locale.h> 44c5c4113dSnw141292 #include <sys/systeminfo.h> 45c5c4113dSnw141292 #include <errno.h> 46c5c4113dSnw141292 #include <sys/wait.h> 47c5c4113dSnw141292 #include <sys/time.h> 48c5c4113dSnw141292 #include <zone.h> 49c5c4113dSnw141292 #include <door.h> 50c8e26105Sjp151216 #include <port.h> 51c5c4113dSnw141292 #include <tsol/label.h> 52c5c4113dSnw141292 #include <sys/resource.h> 53c5c4113dSnw141292 #include <sys/sid.h> 54c5c4113dSnw141292 #include <sys/idmap.h> 55bcced03bSjp151216 #include <pthread.h> 56c5c4113dSnw141292 57c5c4113dSnw141292 static void term_handler(int); 58c5c4113dSnw141292 static void init_idmapd(); 59c5c4113dSnw141292 static void fini_idmapd(); 60c5c4113dSnw141292 61c5c4113dSnw141292 idmapd_state_t _idmapdstate; 62c5c4113dSnw141292 63c5c4113dSnw141292 SVCXPRT *xprt = NULL; 64c5c4113dSnw141292 65c5c4113dSnw141292 static int dfd = -1; /* our door server fildes, for unregistration */ 6671590c90Snw141292 static int degraded = 0; /* whether the FMRI has been marked degraded */ 67c5c4113dSnw141292 68bcced03bSjp151216 69bcced03bSjp151216 static uint32_t num_threads = 0; 70bcced03bSjp151216 static pthread_key_t create_threads_key; 71bcced03bSjp151216 static uint32_t max_threads = 40; 72bcced03bSjp151216 737a8a68f5SJulian Pullen 747a8a68f5SJulian Pullen /* 757a8a68f5SJulian Pullen * The following structure determines where the log messages from idmapdlog() 767a8a68f5SJulian Pullen * go to. It can be stderr (idmapd -d) and/or the real idmapdlog (idmapd). 777a8a68f5SJulian Pullen * 787a8a68f5SJulian Pullen * logstate.max_pri is integer cutoff necessary to silence low-priority 797a8a68f5SJulian Pullen * messages to stderr. idmapdlog has its own means so there a boolean 807a8a68f5SJulian Pullen * logstate.write_idmapdlog is enough. 817a8a68f5SJulian Pullen * 827a8a68f5SJulian Pullen * logstate.degraded is a mode used by idmapd in its degraded state. 837a8a68f5SJulian Pullen */ 847a8a68f5SJulian Pullen 857a8a68f5SJulian Pullen static struct { 867a8a68f5SJulian Pullen boolean_t write_syslog; 877a8a68f5SJulian Pullen int max_pri; /* Max priority written to stderr */ 887a8a68f5SJulian Pullen boolean_t degraded; 897a8a68f5SJulian Pullen } logstate = {B_FALSE, LOG_DEBUG, B_FALSE}; 907a8a68f5SJulian Pullen 91bcced03bSjp151216 /* 92bcced03bSjp151216 * Server door thread start routine. 93bcced03bSjp151216 * 94bcced03bSjp151216 * Set a TSD value to the door thread. This enables the destructor to 95bcced03bSjp151216 * be called when this thread exits. 96bcced03bSjp151216 */ 97bcced03bSjp151216 /*ARGSUSED*/ 98bcced03bSjp151216 static void * 99bcced03bSjp151216 idmapd_door_thread_start(void *arg) 100bcced03bSjp151216 { 101bcced03bSjp151216 static void *value = 0; 102bcced03bSjp151216 103bcced03bSjp151216 /* 104bcced03bSjp151216 * Disable cancellation to avoid memory leaks from not running 105bcced03bSjp151216 * the thread cleanup code. 106bcced03bSjp151216 */ 107bcced03bSjp151216 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 108bcced03bSjp151216 (void) pthread_setspecific(create_threads_key, value); 109bcced03bSjp151216 (void) door_return(NULL, 0, NULL, 0); 110bcced03bSjp151216 111bcced03bSjp151216 /* make lint happy */ 112bcced03bSjp151216 return (NULL); 113bcced03bSjp151216 } 114bcced03bSjp151216 115bcced03bSjp151216 /* 116bcced03bSjp151216 * Server door threads creation 117bcced03bSjp151216 */ 118bcced03bSjp151216 /*ARGSUSED*/ 119bcced03bSjp151216 static void 120bcced03bSjp151216 idmapd_door_thread_create(door_info_t *dip) 121bcced03bSjp151216 { 122bcced03bSjp151216 int num; 123bcced03bSjp151216 pthread_t thread_id; 124bcced03bSjp151216 125bcced03bSjp151216 if ((num = atomic_inc_32_nv(&num_threads)) > max_threads) { 126bcced03bSjp151216 atomic_dec_32(&num_threads); 127bcced03bSjp151216 idmapdlog(LOG_DEBUG, 128bcced03bSjp151216 "thread creation refused - %d threads currently active", 129bcced03bSjp151216 num - 1); 130bcced03bSjp151216 return; 131bcced03bSjp151216 } 132bcced03bSjp151216 (void) pthread_create(&thread_id, NULL, idmapd_door_thread_start, NULL); 133bcced03bSjp151216 idmapdlog(LOG_DEBUG, 134bcced03bSjp151216 "created thread ID %d - %d threads currently active", 135bcced03bSjp151216 thread_id, num); 136bcced03bSjp151216 } 137bcced03bSjp151216 138bcced03bSjp151216 /* 139bcced03bSjp151216 * Server door thread cleanup 140bcced03bSjp151216 */ 141bcced03bSjp151216 /*ARGSUSED*/ 142bcced03bSjp151216 static void 143bcced03bSjp151216 idmapd_door_thread_cleanup(void *arg) 144bcced03bSjp151216 { 145bcced03bSjp151216 int num; 146bcced03bSjp151216 147bcced03bSjp151216 num = atomic_dec_32_nv(&num_threads); 148bcced03bSjp151216 idmapdlog(LOG_DEBUG, 149bcced03bSjp151216 "exiting thread ID %d - %d threads currently active", 150bcced03bSjp151216 pthread_self(), num); 151bcced03bSjp151216 } 152bcced03bSjp151216 153c5c4113dSnw141292 /* 154c5c4113dSnw141292 * This is needed for mech_krb5 -- we run as daemon, yes, but we want 15578b2cb9aSnw141292 * mech_krb5 to think we're root so it can get host/nodename.fqdn 15678b2cb9aSnw141292 * tickets for us so we can authenticate to AD as the machine account 15778b2cb9aSnw141292 * that we are. For more details look at the entry point in mech_krb5 15878b2cb9aSnw141292 * corresponding to gss_init_sec_context(). 15978b2cb9aSnw141292 * 16078b2cb9aSnw141292 * As a side effect of faking our effective UID to mech_krb5 we will use 16178b2cb9aSnw141292 * root's default ccache (/tmp/krb5cc_0). But if that's created by 16278b2cb9aSnw141292 * another process then we won't have access to it: we run as daemon and 16378b2cb9aSnw141292 * keep PRIV_FILE_DAC_READ, which is insufficient to share the ccache 16478b2cb9aSnw141292 * with others. We putenv("KRB5CCNAME=/var/run/idmap/ccache") in main() 16578b2cb9aSnw141292 * to avoid this issue; see main(). 166c5c4113dSnw141292 * 167c5c4113dSnw141292 * Someday we'll have gss/mech_krb5 extensions for acquiring initiator 168c5c4113dSnw141292 * creds with keytabs/raw keys, and someday we'll have extensions to 169c5c4113dSnw141292 * libsasl to specify creds/name to use on the initiator side, and 170c5c4113dSnw141292 * someday we'll have extensions to libldap to pass those through to 171c5c4113dSnw141292 * libsasl. Until then this interposer will have to do. 172c5c4113dSnw141292 * 173c5c4113dSnw141292 * Also, we have to tell lint to shut up: it thinks app_krb5_user_uid() 174c5c4113dSnw141292 * is defined but not used. 175c5c4113dSnw141292 */ 176c5c4113dSnw141292 /*LINTLIBRARY*/ 177c5c4113dSnw141292 uid_t 178c5c4113dSnw141292 app_krb5_user_uid(void) 179c5c4113dSnw141292 { 180c5c4113dSnw141292 return (0); 181c5c4113dSnw141292 } 182c5c4113dSnw141292 183c5c4113dSnw141292 /*ARGSUSED*/ 184c5c4113dSnw141292 static void 1854edd44c5Sjp151216 term_handler(int sig) 1864edd44c5Sjp151216 { 18771590c90Snw141292 idmapdlog(LOG_INFO, "Terminating."); 188c5c4113dSnw141292 fini_idmapd(); 189c5c4113dSnw141292 _exit(0); 190c5c4113dSnw141292 } 191c5c4113dSnw141292 19271590c90Snw141292 /*ARGSUSED*/ 19371590c90Snw141292 static void 19471590c90Snw141292 usr1_handler(int sig) 19571590c90Snw141292 { 1967a8a68f5SJulian Pullen boolean_t saved_debug_mode = _idmapdstate.debug_mode; 19771590c90Snw141292 1987a8a68f5SJulian Pullen _idmapdstate.debug_mode = B_TRUE; 199479ac375Sdm199847 idmap_log_stderr(LOG_DEBUG); 200479ac375Sdm199847 20171590c90Snw141292 print_idmapdstate(); 202479ac375Sdm199847 20371590c90Snw141292 _idmapdstate.debug_mode = saved_debug_mode; 204479ac375Sdm199847 idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG); 205479ac375Sdm199847 20671590c90Snw141292 } 20771590c90Snw141292 208c5c4113dSnw141292 static int pipe_fd = -1; 209c5c4113dSnw141292 210c5c4113dSnw141292 static void 2114edd44c5Sjp151216 daemonize_ready(void) 2124edd44c5Sjp151216 { 213c5c4113dSnw141292 char data = '\0'; 214c5c4113dSnw141292 /* 215c5c4113dSnw141292 * wake the parent 216c5c4113dSnw141292 */ 217c5c4113dSnw141292 (void) write(pipe_fd, &data, 1); 218c5c4113dSnw141292 (void) close(pipe_fd); 219c5c4113dSnw141292 } 220c5c4113dSnw141292 221c5c4113dSnw141292 static int 2224edd44c5Sjp151216 daemonize_start(void) 2234edd44c5Sjp151216 { 224c5c4113dSnw141292 char data; 225c5c4113dSnw141292 int status; 226c5c4113dSnw141292 int devnull; 227c5c4113dSnw141292 int filedes[2]; 228c5c4113dSnw141292 pid_t pid; 229c5c4113dSnw141292 23078b2cb9aSnw141292 (void) sigset(SIGPIPE, SIG_IGN); 231c5c4113dSnw141292 devnull = open("/dev/null", O_RDONLY); 232c5c4113dSnw141292 if (devnull < 0) 233c5c4113dSnw141292 return (-1); 234c5c4113dSnw141292 (void) dup2(devnull, 0); 235c5c4113dSnw141292 (void) dup2(2, 1); /* stderr only */ 236c5c4113dSnw141292 if (pipe(filedes) < 0) 237c5c4113dSnw141292 return (-1); 238c5c4113dSnw141292 if ((pid = fork1()) < 0) 239c5c4113dSnw141292 return (-1); 240c5c4113dSnw141292 if (pid != 0) { 241c5c4113dSnw141292 /* 242c5c4113dSnw141292 * parent 243c5c4113dSnw141292 */ 244c5c4113dSnw141292 (void) close(filedes[1]); 245c5c4113dSnw141292 if (read(filedes[0], &data, 1) == 1) { 246c5c4113dSnw141292 /* presume success */ 247c5c4113dSnw141292 _exit(0); 248c5c4113dSnw141292 } 249c5c4113dSnw141292 status = -1; 250c5c4113dSnw141292 (void) wait4(pid, &status, 0, NULL); 251c5c4113dSnw141292 if (WIFEXITED(status)) 252c5c4113dSnw141292 _exit(WEXITSTATUS(status)); 253c5c4113dSnw141292 else 254c5c4113dSnw141292 _exit(-1); 255c5c4113dSnw141292 } 256c5c4113dSnw141292 257c5c4113dSnw141292 /* 258c5c4113dSnw141292 * child 259c5c4113dSnw141292 */ 260c5c4113dSnw141292 pipe_fd = filedes[1]; 261c5c4113dSnw141292 (void) close(filedes[0]); 262c5c4113dSnw141292 (void) setsid(); 263c5c4113dSnw141292 (void) umask(0077); 264c5c4113dSnw141292 openlog("idmap", LOG_PID, LOG_DAEMON); 265479ac375Sdm199847 266c5c4113dSnw141292 return (0); 267c5c4113dSnw141292 } 268c5c4113dSnw141292 269c5c4113dSnw141292 270c5c4113dSnw141292 int 271c5c4113dSnw141292 main(int argc, char **argv) 272c5c4113dSnw141292 { 273c5c4113dSnw141292 int c; 2742b3ecdebSjp151216 struct rlimit rl; 275c5c4113dSnw141292 27671590c90Snw141292 _idmapdstate.daemon_mode = TRUE; 27771590c90Snw141292 _idmapdstate.debug_mode = FALSE; 27871590c90Snw141292 while ((c = getopt(argc, argv, "d")) != -1) { 279c5c4113dSnw141292 switch (c) { 280c5c4113dSnw141292 case 'd': 28171590c90Snw141292 _idmapdstate.daemon_mode = FALSE; 282c5c4113dSnw141292 break; 283c5c4113dSnw141292 default: 284bbf6f00cSJordan Brown (void) fprintf(stderr, 285bbf6f00cSJordan Brown "Usage: /usr/lib/idmapd [-d]\n"); 28671590c90Snw141292 return (SMF_EXIT_ERR_CONFIG); 287c5c4113dSnw141292 } 288c5c4113dSnw141292 } 289c5c4113dSnw141292 290c5c4113dSnw141292 /* set locale and domain for internationalization */ 291c5c4113dSnw141292 (void) setlocale(LC_ALL, ""); 292c5c4113dSnw141292 (void) textdomain(TEXT_DOMAIN); 293c5c4113dSnw141292 2947a8a68f5SJulian Pullen idmap_set_logger(idmapdlog); 295*c5866007SKeyur Desai adutils_set_logger(idmapdlog); 2967a8a68f5SJulian Pullen idmap_log_syslog(B_TRUE); 297479ac375Sdm199847 idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG); 298479ac375Sdm199847 299bda89588Sjp151216 if (is_system_labeled() && getzoneid() != GLOBAL_ZONEID) { 30071590c90Snw141292 idmapdlog(LOG_ERR, 30171590c90Snw141292 "with Trusted Extensions idmapd runs only in the " 302bda89588Sjp151216 "global zone"); 303c5c4113dSnw141292 exit(1); 304c5c4113dSnw141292 } 305c5c4113dSnw141292 3062b3ecdebSjp151216 /* 3072b3ecdebSjp151216 * Raise the fd limit to max 3082b3ecdebSjp151216 */ 3092b3ecdebSjp151216 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { 3102b3ecdebSjp151216 idmapdlog(LOG_ERR, "getrlimit failed"); 3112b3ecdebSjp151216 } else if (rl.rlim_cur < rl.rlim_max) { 3122b3ecdebSjp151216 rl.rlim_cur = rl.rlim_max; 3132b3ecdebSjp151216 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) 3142b3ecdebSjp151216 idmapdlog(LOG_ERR, 3152b3ecdebSjp151216 "Unable to raise RLIMIT_NOFILE to %d", 3162b3ecdebSjp151216 rl.rlim_cur); 3172b3ecdebSjp151216 } 3182b3ecdebSjp151216 319c5c4113dSnw141292 (void) mutex_init(&_svcstate_lock, USYNC_THREAD, NULL); 320c5c4113dSnw141292 32171590c90Snw141292 if (_idmapdstate.daemon_mode == TRUE) { 322c5c4113dSnw141292 if (daemonize_start() < 0) { 3237a8a68f5SJulian Pullen idmapdlog(LOG_ERR, "unable to daemonize"); 324c5c4113dSnw141292 exit(-1); 325c5c4113dSnw141292 } 326c5c4113dSnw141292 } else 327c5c4113dSnw141292 (void) umask(0077); 328c5c4113dSnw141292 32984decf41Sjp151216 idmap_init_tsd_key(); 33084decf41Sjp151216 331c5c4113dSnw141292 init_idmapd(); 332c5c4113dSnw141292 33378b2cb9aSnw141292 /* signal handlers that should run only after we're initialized */ 33478b2cb9aSnw141292 (void) sigset(SIGTERM, term_handler); 33571590c90Snw141292 (void) sigset(SIGUSR1, usr1_handler); 3360dcc7149Snw141292 (void) sigset(SIGHUP, idmap_cfg_hup_handler); 33778b2cb9aSnw141292 338c5c4113dSnw141292 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 339c5c4113dSnw141292 DAEMON_UID, DAEMON_GID, 340c5c4113dSnw141292 PRIV_PROC_AUDIT, PRIV_FILE_DAC_READ, 341c5c4113dSnw141292 (char *)NULL) == -1) { 34271590c90Snw141292 idmapdlog(LOG_ERR, "unable to drop privileges"); 343c5c4113dSnw141292 exit(1); 344c5c4113dSnw141292 } 345c5c4113dSnw141292 346c5c4113dSnw141292 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 347c5c4113dSnw141292 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 348c5c4113dSnw141292 34971590c90Snw141292 if (_idmapdstate.daemon_mode == TRUE) 350c5c4113dSnw141292 daemonize_ready(); 351c5c4113dSnw141292 352c5c4113dSnw141292 /* With doors RPC this just wastes this thread, oh well */ 353c5c4113dSnw141292 svc_run(); 354c5c4113dSnw141292 return (0); 355c5c4113dSnw141292 } 356c5c4113dSnw141292 357c5c4113dSnw141292 static void 3584edd44c5Sjp151216 init_idmapd() 3594edd44c5Sjp151216 { 360c5c4113dSnw141292 int error; 361d3a612caSnw141292 int connmaxrec = IDMAP_MAX_DOOR_RPC; 362c5c4113dSnw141292 363bcced03bSjp151216 36478b2cb9aSnw141292 /* create directories as root and chown to daemon uid */ 36578b2cb9aSnw141292 if (create_directory(IDMAP_DBDIR, DAEMON_UID, DAEMON_GID) < 0) 36678b2cb9aSnw141292 exit(1); 36778b2cb9aSnw141292 if (create_directory(IDMAP_CACHEDIR, DAEMON_UID, DAEMON_GID) < 0) 36878b2cb9aSnw141292 exit(1); 36978b2cb9aSnw141292 37078b2cb9aSnw141292 /* 37178b2cb9aSnw141292 * Set KRB5CCNAME in the environment. See app_krb5_user_uid() 372e3c2d6aaSnw141292 * for more details. We blow away the existing one, if there is 373e3c2d6aaSnw141292 * one. 37478b2cb9aSnw141292 */ 375e3c2d6aaSnw141292 (void) unlink(IDMAP_CACHEDIR "/ccache"); 37678b2cb9aSnw141292 putenv("KRB5CCNAME=" IDMAP_CACHEDIR "/ccache"); 37778b2cb9aSnw141292 378c5c4113dSnw141292 if (sysinfo(SI_HOSTNAME, _idmapdstate.hostname, 379c5c4113dSnw141292 sizeof (_idmapdstate.hostname)) == -1) { 380c5c4113dSnw141292 error = errno; 38171590c90Snw141292 idmapdlog(LOG_ERR, "unable to determine hostname, error: %d", 382c5c4113dSnw141292 error); 383c5c4113dSnw141292 exit(1); 384c5c4113dSnw141292 } 385c5c4113dSnw141292 386e8c27ec8Sbaban if ((error = init_mapping_system()) < 0) { 38771590c90Snw141292 idmapdlog(LOG_ERR, "unable to initialize mapping system"); 388e8c27ec8Sbaban exit(error < -2 ? SMF_EXIT_ERR_CONFIG : 1); 389c5c4113dSnw141292 } 390c5c4113dSnw141292 391bcced03bSjp151216 (void) door_server_create(idmapd_door_thread_create); 392bcced03bSjp151216 if ((error = pthread_key_create(&create_threads_key, 393bcced03bSjp151216 idmapd_door_thread_cleanup)) != 0) { 394bcced03bSjp151216 idmapdlog(LOG_ERR, "unable to create threads key (%s)", 395bcced03bSjp151216 strerror(error)); 396bcced03bSjp151216 goto errout; 397bcced03bSjp151216 } 398bcced03bSjp151216 399d3a612caSnw141292 xprt = svc_door_create(idmap_prog_1, IDMAP_PROG, IDMAP_V1, connmaxrec); 400c5c4113dSnw141292 if (xprt == NULL) { 40171590c90Snw141292 idmapdlog(LOG_ERR, "unable to create door RPC service"); 402c5c4113dSnw141292 goto errout; 403c5c4113dSnw141292 } 404c5c4113dSnw141292 4058e228215Sdm199847 if (!svc_control(xprt, SVCSET_CONNMAXREC, &connmaxrec)) { 40671590c90Snw141292 idmapdlog(LOG_ERR, "unable to limit RPC request size"); 4078e228215Sdm199847 goto errout; 4088e228215Sdm199847 } 4098e228215Sdm199847 410c5c4113dSnw141292 dfd = xprt->xp_fd; 411c5c4113dSnw141292 412c5c4113dSnw141292 if (dfd == -1) { 41371590c90Snw141292 idmapdlog(LOG_ERR, "unable to register door"); 414c5c4113dSnw141292 goto errout; 415c5c4113dSnw141292 } 4169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((error = __idmap_reg(dfd)) != 0) { 41771590c90Snw141292 idmapdlog(LOG_ERR, "unable to register door (%s)", 418bda89588Sjp151216 strerror(errno)); 419c5c4113dSnw141292 goto errout; 420c5c4113dSnw141292 } 421c5c4113dSnw141292 422c5c4113dSnw141292 if ((error = allocids(_idmapdstate.new_eph_db, 423c5c4113dSnw141292 8192, &_idmapdstate.next_uid, 424c5c4113dSnw141292 8192, &_idmapdstate.next_gid)) != 0) { 42571590c90Snw141292 idmapdlog(LOG_ERR, "unable to allocate ephemeral IDs (%s)", 42671590c90Snw141292 strerror(errno)); 4279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.next_uid = IDMAP_SENTINEL_PID; 4289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.limit_uid = IDMAP_SENTINEL_PID; 4299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.next_gid = IDMAP_SENTINEL_PID; 4309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.limit_gid = IDMAP_SENTINEL_PID; 431c5c4113dSnw141292 } else { 432c5c4113dSnw141292 _idmapdstate.limit_uid = _idmapdstate.next_uid + 8192; 433c5c4113dSnw141292 _idmapdstate.limit_gid = _idmapdstate.next_gid + 8192; 434c5c4113dSnw141292 } 435c5c4113dSnw141292 436c5c4113dSnw141292 print_idmapdstate(); 437c5c4113dSnw141292 438c5c4113dSnw141292 return; 439c5c4113dSnw141292 440c5c4113dSnw141292 errout: 441c5c4113dSnw141292 fini_idmapd(); 442c5c4113dSnw141292 exit(1); 443c5c4113dSnw141292 } 444c5c4113dSnw141292 445c5c4113dSnw141292 static void 4464edd44c5Sjp151216 fini_idmapd() 4474edd44c5Sjp151216 { 4489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States __idmap_unreg(dfd); 449c5c4113dSnw141292 fini_mapping_system(); 450c5c4113dSnw141292 if (xprt != NULL) 451c5c4113dSnw141292 svc_destroy(xprt); 452c5c4113dSnw141292 } 453c5c4113dSnw141292 45471590c90Snw141292 static 45571590c90Snw141292 const char * 45671590c90Snw141292 get_fmri(void) 45771590c90Snw141292 { 45871590c90Snw141292 static char *fmri = NULL; 45971590c90Snw141292 static char buf[60]; 46071590c90Snw141292 char *s; 46171590c90Snw141292 46271590c90Snw141292 membar_consumer(); 46371590c90Snw141292 s = fmri; 46471590c90Snw141292 if (s != NULL && *s == '\0') 46571590c90Snw141292 return (NULL); 46671590c90Snw141292 else if (s != NULL) 46771590c90Snw141292 return (s); 46871590c90Snw141292 46971590c90Snw141292 if ((s = getenv("SMF_FMRI")) == NULL || strlen(s) >= sizeof (buf)) 47071590c90Snw141292 buf[0] = '\0'; 47171590c90Snw141292 else 47271590c90Snw141292 (void) strlcpy(buf, s, sizeof (buf)); 47371590c90Snw141292 47471590c90Snw141292 membar_producer(); 47571590c90Snw141292 fmri = buf; 47671590c90Snw141292 47771590c90Snw141292 return (get_fmri()); 47871590c90Snw141292 } 47971590c90Snw141292 48071590c90Snw141292 /* 48171590c90Snw141292 * Wrappers for smf_degrade/restore_instance() 48271590c90Snw141292 * 48371590c90Snw141292 * smf_restore_instance() is too heavy duty to be calling every time we 48471590c90Snw141292 * have a successful AD name<->SID lookup. 48571590c90Snw141292 */ 48671590c90Snw141292 void 487349d5d8fSnw141292 degrade_svc(int poke_discovery, const char *reason) 48871590c90Snw141292 { 48971590c90Snw141292 const char *fmri; 49071590c90Snw141292 49171590c90Snw141292 membar_consumer(); 49271590c90Snw141292 if (degraded) 49371590c90Snw141292 return; 494349d5d8fSnw141292 495349d5d8fSnw141292 idmapdlog(LOG_ERR, "Degraded operation (%s). If you are running an " 496349d5d8fSnw141292 "SMB server in workgroup mode, or if you're not running an SMB " 497349d5d8fSnw141292 "server, then you can ignore this message", reason); 498349d5d8fSnw141292 49971590c90Snw141292 membar_producer(); 50071590c90Snw141292 degraded = 1; 5017a8a68f5SJulian Pullen idmap_log_degraded(B_TRUE); 50271590c90Snw141292 50371590c90Snw141292 if ((fmri = get_fmri()) != NULL) 50471590c90Snw141292 (void) smf_degrade_instance(fmri, 0); 505*c5866007SKeyur Desai 506*c5866007SKeyur Desai /* 507*c5866007SKeyur Desai * If the config update thread is in a state where auto-discovery could 508*c5866007SKeyur Desai * be re-tried, then this will make it try it -- a sort of auto-refresh. 509*c5866007SKeyur Desai */ 510*c5866007SKeyur Desai if (poke_discovery) 511*c5866007SKeyur Desai idmap_cfg_poke_updates(); 51271590c90Snw141292 } 51371590c90Snw141292 51471590c90Snw141292 void 51571590c90Snw141292 restore_svc(void) 51671590c90Snw141292 { 51771590c90Snw141292 const char *fmri; 51871590c90Snw141292 51971590c90Snw141292 membar_consumer(); 52071590c90Snw141292 if (!degraded) 52171590c90Snw141292 return; 52271590c90Snw141292 52371590c90Snw141292 if ((fmri = get_fmri()) == NULL) 52471590c90Snw141292 (void) smf_restore_instance(fmri); 52571590c90Snw141292 52671590c90Snw141292 membar_producer(); 52771590c90Snw141292 degraded = 0; 5287a8a68f5SJulian Pullen idmap_log_degraded(B_FALSE); 529479ac375Sdm199847 530349d5d8fSnw141292 idmapdlog(LOG_NOTICE, "Normal operation restored"); 53171590c90Snw141292 } 53271590c90Snw141292 5337a8a68f5SJulian Pullen 5347a8a68f5SJulian Pullen /* printflike */ 535c5c4113dSnw141292 void 5367a8a68f5SJulian Pullen idmapdlog(int pri, const char *format, ...) { 537c5c4113dSnw141292 va_list args; 538c5c4113dSnw141292 5397a8a68f5SJulian Pullen if (pri <= logstate.max_pri) { 540c5c4113dSnw141292 va_start(args, format); 541c5c4113dSnw141292 (void) vfprintf(stderr, format, args); 542c5c4113dSnw141292 (void) fprintf(stderr, "\n"); 5437a8a68f5SJulian Pullen va_end(args); 544c5c4113dSnw141292 } 54571590c90Snw141292 54671590c90Snw141292 /* 54771590c90Snw141292 * We don't want to fill up the logs with useless messages when 54871590c90Snw141292 * we're degraded, but we still want to log. 54971590c90Snw141292 */ 5507a8a68f5SJulian Pullen if (logstate.degraded) 55171590c90Snw141292 pri = LOG_DEBUG; 55271590c90Snw141292 5537a8a68f5SJulian Pullen if (logstate.write_syslog) { 5547a8a68f5SJulian Pullen va_start(args, format); 5557a8a68f5SJulian Pullen vsyslog(pri, format, args); 556c5c4113dSnw141292 va_end(args); 557c5c4113dSnw141292 } 5587a8a68f5SJulian Pullen } 5597a8a68f5SJulian Pullen 5607a8a68f5SJulian Pullen void 5617a8a68f5SJulian Pullen idmap_log_stderr(int pri) 5627a8a68f5SJulian Pullen { 5637a8a68f5SJulian Pullen logstate.max_pri = pri; 5647a8a68f5SJulian Pullen } 5657a8a68f5SJulian Pullen 5667a8a68f5SJulian Pullen void 5677a8a68f5SJulian Pullen idmap_log_syslog(boolean_t what) 5687a8a68f5SJulian Pullen { 5697a8a68f5SJulian Pullen logstate.write_syslog = what; 5707a8a68f5SJulian Pullen } 5717a8a68f5SJulian Pullen 5727a8a68f5SJulian Pullen void 5737a8a68f5SJulian Pullen idmap_log_degraded(boolean_t what) 5747a8a68f5SJulian Pullen { 5757a8a68f5SJulian Pullen logstate.degraded = what; 5767a8a68f5SJulian Pullen } 577