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 /* 22c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24c5c4113dSnw141292 */ 25c5c4113dSnw141292 26c5c4113dSnw141292 27c5c4113dSnw141292 /* 28c5c4113dSnw141292 * main() of idmapd(1M) 29c5c4113dSnw141292 */ 30c5c4113dSnw141292 31c5c4113dSnw141292 #include "idmapd.h" 3271590c90Snw141292 #include <atomic.h> 33c5c4113dSnw141292 #include <signal.h> 34c5c4113dSnw141292 #include <rpc/pmap_clnt.h> /* for pmap_unset */ 35c5c4113dSnw141292 #include <string.h> /* strcmp */ 36c5c4113dSnw141292 #include <unistd.h> /* setsid */ 37c5c4113dSnw141292 #include <sys/types.h> 38c5c4113dSnw141292 #include <memory.h> 39c5c4113dSnw141292 #include <stropts.h> 40c5c4113dSnw141292 #include <netconfig.h> 41c5c4113dSnw141292 #include <sys/resource.h> /* rlimit */ 42c5c4113dSnw141292 #include <rpcsvc/daemon_utils.h> /* DAEMON_UID and DAEMON_GID */ 43c5c4113dSnw141292 #include <priv_utils.h> /* privileges */ 44c5c4113dSnw141292 #include <locale.h> 45c5c4113dSnw141292 #include <sys/systeminfo.h> 46c5c4113dSnw141292 #include <errno.h> 47c5c4113dSnw141292 #include <sys/wait.h> 48c5c4113dSnw141292 #include <sys/time.h> 49c5c4113dSnw141292 #include <zone.h> 50c5c4113dSnw141292 #include <door.h> 51c8e26105Sjp151216 #include <port.h> 52c5c4113dSnw141292 #include <tsol/label.h> 53c5c4113dSnw141292 #include <sys/resource.h> 54c5c4113dSnw141292 #include <sys/sid.h> 55c5c4113dSnw141292 #include <sys/idmap.h> 56bcced03bSjp151216 #include <pthread.h> 57148c5f43SAlan Wright #include <stdarg.h> 58148c5f43SAlan Wright #include <assert.h> 59148c5f43SAlan Wright #include <note.h> 60c5c4113dSnw141292 61*b3700b07SGordon Ross #define CBUFSIZ 26 /* ctime(3c) */ 62*b3700b07SGordon Ross 63c5c4113dSnw141292 static void term_handler(int); 64c5c4113dSnw141292 static void init_idmapd(); 65c5c4113dSnw141292 static void fini_idmapd(); 66c5c4113dSnw141292 67*b3700b07SGordon Ross /* The DC Locator lives inside idmap (for now). */ 68*b3700b07SGordon Ross extern void init_dc_locator(void); 69*b3700b07SGordon Ross extern void fini_dc_locator(void); 70*b3700b07SGordon Ross 71c5c4113dSnw141292 idmapd_state_t _idmapdstate; 72c5c4113dSnw141292 73c5c4113dSnw141292 SVCXPRT *xprt = NULL; 74c5c4113dSnw141292 75c5c4113dSnw141292 static int dfd = -1; /* our door server fildes, for unregistration */ 76148c5f43SAlan Wright static boolean_t degraded = B_FALSE; 77c5c4113dSnw141292 78bcced03bSjp151216 79bcced03bSjp151216 static uint32_t num_threads = 0; 80bcced03bSjp151216 static pthread_key_t create_threads_key; 81bcced03bSjp151216 static uint32_t max_threads = 40; 82bcced03bSjp151216 83bcced03bSjp151216 /* 84bcced03bSjp151216 * Server door thread start routine. 85bcced03bSjp151216 * 86bcced03bSjp151216 * Set a TSD value to the door thread. This enables the destructor to 87bcced03bSjp151216 * be called when this thread exits. 88bcced03bSjp151216 */ 89bcced03bSjp151216 /*ARGSUSED*/ 90bcced03bSjp151216 static void * 91bcced03bSjp151216 idmapd_door_thread_start(void *arg) 92bcced03bSjp151216 { 93bcced03bSjp151216 static void *value = 0; 94bcced03bSjp151216 95bcced03bSjp151216 /* 96bcced03bSjp151216 * Disable cancellation to avoid memory leaks from not running 97bcced03bSjp151216 * the thread cleanup code. 98bcced03bSjp151216 */ 99bcced03bSjp151216 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 100bcced03bSjp151216 (void) pthread_setspecific(create_threads_key, value); 101bcced03bSjp151216 (void) door_return(NULL, 0, NULL, 0); 102bcced03bSjp151216 103bcced03bSjp151216 /* make lint happy */ 104bcced03bSjp151216 return (NULL); 105bcced03bSjp151216 } 106bcced03bSjp151216 107bcced03bSjp151216 /* 108bcced03bSjp151216 * Server door threads creation 109bcced03bSjp151216 */ 110bcced03bSjp151216 /*ARGSUSED*/ 111bcced03bSjp151216 static void 112bcced03bSjp151216 idmapd_door_thread_create(door_info_t *dip) 113bcced03bSjp151216 { 114bcced03bSjp151216 int num; 115bcced03bSjp151216 pthread_t thread_id; 116bcced03bSjp151216 117bcced03bSjp151216 if ((num = atomic_inc_32_nv(&num_threads)) > max_threads) { 118bcced03bSjp151216 atomic_dec_32(&num_threads); 119bcced03bSjp151216 idmapdlog(LOG_DEBUG, 120bcced03bSjp151216 "thread creation refused - %d threads currently active", 121bcced03bSjp151216 num - 1); 122bcced03bSjp151216 return; 123bcced03bSjp151216 } 124bcced03bSjp151216 (void) pthread_create(&thread_id, NULL, idmapd_door_thread_start, NULL); 125bcced03bSjp151216 idmapdlog(LOG_DEBUG, 126bcced03bSjp151216 "created thread ID %d - %d threads currently active", 127bcced03bSjp151216 thread_id, num); 128bcced03bSjp151216 } 129bcced03bSjp151216 130bcced03bSjp151216 /* 131bcced03bSjp151216 * Server door thread cleanup 132bcced03bSjp151216 */ 133bcced03bSjp151216 /*ARGSUSED*/ 134bcced03bSjp151216 static void 135bcced03bSjp151216 idmapd_door_thread_cleanup(void *arg) 136bcced03bSjp151216 { 137bcced03bSjp151216 int num; 138bcced03bSjp151216 139bcced03bSjp151216 num = atomic_dec_32_nv(&num_threads); 140bcced03bSjp151216 idmapdlog(LOG_DEBUG, 141bcced03bSjp151216 "exiting thread ID %d - %d threads currently active", 142bcced03bSjp151216 pthread_self(), num); 143bcced03bSjp151216 } 144bcced03bSjp151216 145c5c4113dSnw141292 /* 146c5c4113dSnw141292 * This is needed for mech_krb5 -- we run as daemon, yes, but we want 14778b2cb9aSnw141292 * mech_krb5 to think we're root so it can get host/nodename.fqdn 14878b2cb9aSnw141292 * tickets for us so we can authenticate to AD as the machine account 14978b2cb9aSnw141292 * that we are. For more details look at the entry point in mech_krb5 15078b2cb9aSnw141292 * corresponding to gss_init_sec_context(). 15178b2cb9aSnw141292 * 15278b2cb9aSnw141292 * As a side effect of faking our effective UID to mech_krb5 we will use 15378b2cb9aSnw141292 * root's default ccache (/tmp/krb5cc_0). But if that's created by 15478b2cb9aSnw141292 * another process then we won't have access to it: we run as daemon and 15578b2cb9aSnw141292 * keep PRIV_FILE_DAC_READ, which is insufficient to share the ccache 15678b2cb9aSnw141292 * with others. We putenv("KRB5CCNAME=/var/run/idmap/ccache") in main() 15778b2cb9aSnw141292 * to avoid this issue; see main(). 158c5c4113dSnw141292 * 159c5c4113dSnw141292 * Someday we'll have gss/mech_krb5 extensions for acquiring initiator 160c5c4113dSnw141292 * creds with keytabs/raw keys, and someday we'll have extensions to 161c5c4113dSnw141292 * libsasl to specify creds/name to use on the initiator side, and 162c5c4113dSnw141292 * someday we'll have extensions to libldap to pass those through to 163c5c4113dSnw141292 * libsasl. Until then this interposer will have to do. 164c5c4113dSnw141292 * 165c5c4113dSnw141292 * Also, we have to tell lint to shut up: it thinks app_krb5_user_uid() 166c5c4113dSnw141292 * is defined but not used. 167c5c4113dSnw141292 */ 168c5c4113dSnw141292 /*LINTLIBRARY*/ 169c5c4113dSnw141292 uid_t 170c5c4113dSnw141292 app_krb5_user_uid(void) 171c5c4113dSnw141292 { 172c5c4113dSnw141292 return (0); 173c5c4113dSnw141292 } 174c5c4113dSnw141292 175c5c4113dSnw141292 /*ARGSUSED*/ 176c5c4113dSnw141292 static void 1774edd44c5Sjp151216 term_handler(int sig) 1784edd44c5Sjp151216 { 17971590c90Snw141292 idmapdlog(LOG_INFO, "Terminating."); 180*b3700b07SGordon Ross fini_dc_locator(); 181c5c4113dSnw141292 fini_idmapd(); 182c5c4113dSnw141292 _exit(0); 183c5c4113dSnw141292 } 184c5c4113dSnw141292 18571590c90Snw141292 /*ARGSUSED*/ 18671590c90Snw141292 static void 18771590c90Snw141292 usr1_handler(int sig) 18871590c90Snw141292 { 189148c5f43SAlan Wright NOTE(ARGUNUSED(sig)) 19071590c90Snw141292 print_idmapdstate(); 19171590c90Snw141292 } 19271590c90Snw141292 193c5c4113dSnw141292 static int pipe_fd = -1; 194c5c4113dSnw141292 195c5c4113dSnw141292 static void 1964edd44c5Sjp151216 daemonize_ready(void) 1974edd44c5Sjp151216 { 198c5c4113dSnw141292 char data = '\0'; 199c5c4113dSnw141292 /* 200c5c4113dSnw141292 * wake the parent 201c5c4113dSnw141292 */ 202c5c4113dSnw141292 (void) write(pipe_fd, &data, 1); 203c5c4113dSnw141292 (void) close(pipe_fd); 204c5c4113dSnw141292 } 205c5c4113dSnw141292 206c5c4113dSnw141292 static int 2074edd44c5Sjp151216 daemonize_start(void) 2084edd44c5Sjp151216 { 209c5c4113dSnw141292 char data; 210c5c4113dSnw141292 int status; 211c5c4113dSnw141292 int devnull; 212c5c4113dSnw141292 int filedes[2]; 213c5c4113dSnw141292 pid_t pid; 214c5c4113dSnw141292 21578b2cb9aSnw141292 (void) sigset(SIGPIPE, SIG_IGN); 216c5c4113dSnw141292 devnull = open("/dev/null", O_RDONLY); 217c5c4113dSnw141292 if (devnull < 0) 218c5c4113dSnw141292 return (-1); 219c5c4113dSnw141292 (void) dup2(devnull, 0); 220c5c4113dSnw141292 (void) dup2(2, 1); /* stderr only */ 221c5c4113dSnw141292 if (pipe(filedes) < 0) 222c5c4113dSnw141292 return (-1); 223c5c4113dSnw141292 if ((pid = fork1()) < 0) 224c5c4113dSnw141292 return (-1); 225c5c4113dSnw141292 if (pid != 0) { 226c5c4113dSnw141292 /* 227c5c4113dSnw141292 * parent 228c5c4113dSnw141292 */ 229c5c4113dSnw141292 (void) close(filedes[1]); 230c5c4113dSnw141292 if (read(filedes[0], &data, 1) == 1) { 231c5c4113dSnw141292 /* presume success */ 232c5c4113dSnw141292 _exit(0); 233c5c4113dSnw141292 } 234c5c4113dSnw141292 status = -1; 235c5c4113dSnw141292 (void) wait4(pid, &status, 0, NULL); 236c5c4113dSnw141292 if (WIFEXITED(status)) 237c5c4113dSnw141292 _exit(WEXITSTATUS(status)); 238c5c4113dSnw141292 else 239c5c4113dSnw141292 _exit(-1); 240c5c4113dSnw141292 } 241c5c4113dSnw141292 242c5c4113dSnw141292 /* 243c5c4113dSnw141292 * child 244c5c4113dSnw141292 */ 245c5c4113dSnw141292 pipe_fd = filedes[1]; 246c5c4113dSnw141292 (void) close(filedes[0]); 247c5c4113dSnw141292 (void) setsid(); 248c5c4113dSnw141292 (void) umask(0077); 249c5c4113dSnw141292 openlog("idmap", LOG_PID, LOG_DAEMON); 250479ac375Sdm199847 251c5c4113dSnw141292 return (0); 252c5c4113dSnw141292 } 253c5c4113dSnw141292 254c5c4113dSnw141292 255c5c4113dSnw141292 int 256c5c4113dSnw141292 main(int argc, char **argv) 257c5c4113dSnw141292 { 258c5c4113dSnw141292 int c; 2592b3ecdebSjp151216 struct rlimit rl; 260c5c4113dSnw141292 261*b3700b07SGordon Ross if (rwlock_init(&_idmapdstate.rwlk_cfg, USYNC_THREAD, NULL) != 0) 262*b3700b07SGordon Ross return (-1); 263*b3700b07SGordon Ross if (mutex_init(&_idmapdstate.addisc_lk, USYNC_THREAD, NULL) != 0) 264*b3700b07SGordon Ross return (-1); 265*b3700b07SGordon Ross if (cond_init(&_idmapdstate.addisc_cv, USYNC_THREAD, NULL) != 0) 266*b3700b07SGordon Ross return (-1); 267*b3700b07SGordon Ross 26871590c90Snw141292 _idmapdstate.daemon_mode = TRUE; 26971590c90Snw141292 while ((c = getopt(argc, argv, "d")) != -1) { 270c5c4113dSnw141292 switch (c) { 271c5c4113dSnw141292 case 'd': 27271590c90Snw141292 _idmapdstate.daemon_mode = FALSE; 273c5c4113dSnw141292 break; 274c5c4113dSnw141292 default: 275bbf6f00cSJordan Brown (void) fprintf(stderr, 276bbf6f00cSJordan Brown "Usage: /usr/lib/idmapd [-d]\n"); 27771590c90Snw141292 return (SMF_EXIT_ERR_CONFIG); 278c5c4113dSnw141292 } 279c5c4113dSnw141292 } 280c5c4113dSnw141292 281c5c4113dSnw141292 /* set locale and domain for internationalization */ 282c5c4113dSnw141292 (void) setlocale(LC_ALL, ""); 283c5c4113dSnw141292 (void) textdomain(TEXT_DOMAIN); 284c5c4113dSnw141292 2857a8a68f5SJulian Pullen idmap_set_logger(idmapdlog); 286c5866007SKeyur Desai adutils_set_logger(idmapdlog); 287479ac375Sdm199847 288bda89588Sjp151216 if (is_system_labeled() && getzoneid() != GLOBAL_ZONEID) { 28971590c90Snw141292 idmapdlog(LOG_ERR, 29071590c90Snw141292 "with Trusted Extensions idmapd runs only in the " 291bda89588Sjp151216 "global zone"); 292c5c4113dSnw141292 exit(1); 293c5c4113dSnw141292 } 294c5c4113dSnw141292 2952b3ecdebSjp151216 /* 2962b3ecdebSjp151216 * Raise the fd limit to max 2972b3ecdebSjp151216 */ 2982b3ecdebSjp151216 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) { 2992b3ecdebSjp151216 idmapdlog(LOG_ERR, "getrlimit failed"); 3002b3ecdebSjp151216 } else if (rl.rlim_cur < rl.rlim_max) { 3012b3ecdebSjp151216 rl.rlim_cur = rl.rlim_max; 3022b3ecdebSjp151216 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) 3032b3ecdebSjp151216 idmapdlog(LOG_ERR, 3042b3ecdebSjp151216 "Unable to raise RLIMIT_NOFILE to %d", 3052b3ecdebSjp151216 rl.rlim_cur); 3062b3ecdebSjp151216 } 3072b3ecdebSjp151216 308c5c4113dSnw141292 (void) mutex_init(&_svcstate_lock, USYNC_THREAD, NULL); 309c5c4113dSnw141292 31071590c90Snw141292 if (_idmapdstate.daemon_mode == TRUE) { 311c5c4113dSnw141292 if (daemonize_start() < 0) { 3127a8a68f5SJulian Pullen idmapdlog(LOG_ERR, "unable to daemonize"); 313c5c4113dSnw141292 exit(-1); 314c5c4113dSnw141292 } 315c5c4113dSnw141292 } else 316c5c4113dSnw141292 (void) umask(0077); 317c5c4113dSnw141292 31884decf41Sjp151216 idmap_init_tsd_key(); 31984decf41Sjp151216 320c5c4113dSnw141292 init_idmapd(); 321*b3700b07SGordon Ross init_dc_locator(); 322c5c4113dSnw141292 32378b2cb9aSnw141292 /* signal handlers that should run only after we're initialized */ 32478b2cb9aSnw141292 (void) sigset(SIGTERM, term_handler); 32571590c90Snw141292 (void) sigset(SIGUSR1, usr1_handler); 3260dcc7149Snw141292 (void) sigset(SIGHUP, idmap_cfg_hup_handler); 32778b2cb9aSnw141292 328c5c4113dSnw141292 if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 329c5c4113dSnw141292 DAEMON_UID, DAEMON_GID, 330c5c4113dSnw141292 PRIV_PROC_AUDIT, PRIV_FILE_DAC_READ, 331c5c4113dSnw141292 (char *)NULL) == -1) { 33271590c90Snw141292 idmapdlog(LOG_ERR, "unable to drop privileges"); 333c5c4113dSnw141292 exit(1); 334c5c4113dSnw141292 } 335c5c4113dSnw141292 336c5c4113dSnw141292 __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, 337c5c4113dSnw141292 PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); 338c5c4113dSnw141292 33971590c90Snw141292 if (_idmapdstate.daemon_mode == TRUE) 340c5c4113dSnw141292 daemonize_ready(); 341c5c4113dSnw141292 342c5c4113dSnw141292 /* With doors RPC this just wastes this thread, oh well */ 343c5c4113dSnw141292 svc_run(); 344c5c4113dSnw141292 return (0); 345c5c4113dSnw141292 } 346c5c4113dSnw141292 347c5c4113dSnw141292 static void 3484edd44c5Sjp151216 init_idmapd() 3494edd44c5Sjp151216 { 350c5c4113dSnw141292 int error; 351d3a612caSnw141292 int connmaxrec = IDMAP_MAX_DOOR_RPC; 352c5c4113dSnw141292 353bcced03bSjp151216 35478b2cb9aSnw141292 /* create directories as root and chown to daemon uid */ 35578b2cb9aSnw141292 if (create_directory(IDMAP_DBDIR, DAEMON_UID, DAEMON_GID) < 0) 35678b2cb9aSnw141292 exit(1); 35778b2cb9aSnw141292 if (create_directory(IDMAP_CACHEDIR, DAEMON_UID, DAEMON_GID) < 0) 35878b2cb9aSnw141292 exit(1); 35978b2cb9aSnw141292 36078b2cb9aSnw141292 /* 36178b2cb9aSnw141292 * Set KRB5CCNAME in the environment. See app_krb5_user_uid() 362e3c2d6aaSnw141292 * for more details. We blow away the existing one, if there is 363e3c2d6aaSnw141292 * one. 36478b2cb9aSnw141292 */ 365e3c2d6aaSnw141292 (void) unlink(IDMAP_CACHEDIR "/ccache"); 366148c5f43SAlan Wright (void) putenv("KRB5CCNAME=" IDMAP_CACHEDIR "/ccache"); 367*b3700b07SGordon Ross (void) putenv("MS_INTEROP=1"); 36878b2cb9aSnw141292 369c5c4113dSnw141292 if (sysinfo(SI_HOSTNAME, _idmapdstate.hostname, 370c5c4113dSnw141292 sizeof (_idmapdstate.hostname)) == -1) { 371c5c4113dSnw141292 error = errno; 37271590c90Snw141292 idmapdlog(LOG_ERR, "unable to determine hostname, error: %d", 373c5c4113dSnw141292 error); 374c5c4113dSnw141292 exit(1); 375c5c4113dSnw141292 } 376c5c4113dSnw141292 377e8c27ec8Sbaban if ((error = init_mapping_system()) < 0) { 37871590c90Snw141292 idmapdlog(LOG_ERR, "unable to initialize mapping system"); 379e8c27ec8Sbaban exit(error < -2 ? SMF_EXIT_ERR_CONFIG : 1); 380c5c4113dSnw141292 } 381c5c4113dSnw141292 382bcced03bSjp151216 (void) door_server_create(idmapd_door_thread_create); 383bcced03bSjp151216 if ((error = pthread_key_create(&create_threads_key, 384bcced03bSjp151216 idmapd_door_thread_cleanup)) != 0) { 385bcced03bSjp151216 idmapdlog(LOG_ERR, "unable to create threads key (%s)", 386bcced03bSjp151216 strerror(error)); 387bcced03bSjp151216 goto errout; 388bcced03bSjp151216 } 389bcced03bSjp151216 390d3a612caSnw141292 xprt = svc_door_create(idmap_prog_1, IDMAP_PROG, IDMAP_V1, connmaxrec); 391c5c4113dSnw141292 if (xprt == NULL) { 39271590c90Snw141292 idmapdlog(LOG_ERR, "unable to create door RPC service"); 393c5c4113dSnw141292 goto errout; 394c5c4113dSnw141292 } 395c5c4113dSnw141292 3968e228215Sdm199847 if (!svc_control(xprt, SVCSET_CONNMAXREC, &connmaxrec)) { 39771590c90Snw141292 idmapdlog(LOG_ERR, "unable to limit RPC request size"); 3988e228215Sdm199847 goto errout; 3998e228215Sdm199847 } 4008e228215Sdm199847 401c5c4113dSnw141292 dfd = xprt->xp_fd; 402c5c4113dSnw141292 403c5c4113dSnw141292 if (dfd == -1) { 40471590c90Snw141292 idmapdlog(LOG_ERR, "unable to register door"); 405c5c4113dSnw141292 goto errout; 406c5c4113dSnw141292 } 4079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((error = __idmap_reg(dfd)) != 0) { 40871590c90Snw141292 idmapdlog(LOG_ERR, "unable to register door (%s)", 409bda89588Sjp151216 strerror(errno)); 410c5c4113dSnw141292 goto errout; 411c5c4113dSnw141292 } 412c5c4113dSnw141292 413c5c4113dSnw141292 if ((error = allocids(_idmapdstate.new_eph_db, 414c5c4113dSnw141292 8192, &_idmapdstate.next_uid, 415c5c4113dSnw141292 8192, &_idmapdstate.next_gid)) != 0) { 41671590c90Snw141292 idmapdlog(LOG_ERR, "unable to allocate ephemeral IDs (%s)", 41771590c90Snw141292 strerror(errno)); 4189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.next_uid = IDMAP_SENTINEL_PID; 4199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.limit_uid = IDMAP_SENTINEL_PID; 4209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.next_gid = IDMAP_SENTINEL_PID; 4219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States _idmapdstate.limit_gid = IDMAP_SENTINEL_PID; 422c5c4113dSnw141292 } else { 423c5c4113dSnw141292 _idmapdstate.limit_uid = _idmapdstate.next_uid + 8192; 424c5c4113dSnw141292 _idmapdstate.limit_gid = _idmapdstate.next_gid + 8192; 425c5c4113dSnw141292 } 426c5c4113dSnw141292 427148c5f43SAlan Wright if (DBG(CONFIG, 1)) 428c5c4113dSnw141292 print_idmapdstate(); 429c5c4113dSnw141292 430c5c4113dSnw141292 return; 431c5c4113dSnw141292 432c5c4113dSnw141292 errout: 433c5c4113dSnw141292 fini_idmapd(); 434c5c4113dSnw141292 exit(1); 435c5c4113dSnw141292 } 436c5c4113dSnw141292 437c5c4113dSnw141292 static void 4384edd44c5Sjp151216 fini_idmapd() 4394edd44c5Sjp151216 { 440148c5f43SAlan Wright (void) __idmap_unreg(dfd); 441c5c4113dSnw141292 fini_mapping_system(); 442c5c4113dSnw141292 if (xprt != NULL) 443c5c4113dSnw141292 svc_destroy(xprt); 444c5c4113dSnw141292 } 445c5c4113dSnw141292 44671590c90Snw141292 static 44771590c90Snw141292 const char * 44871590c90Snw141292 get_fmri(void) 44971590c90Snw141292 { 45071590c90Snw141292 static char *fmri = NULL; 45171590c90Snw141292 static char buf[60]; 45271590c90Snw141292 char *s; 45371590c90Snw141292 45471590c90Snw141292 membar_consumer(); 45571590c90Snw141292 s = fmri; 45671590c90Snw141292 if (s != NULL && *s == '\0') 45771590c90Snw141292 return (NULL); 45871590c90Snw141292 else if (s != NULL) 45971590c90Snw141292 return (s); 46071590c90Snw141292 46171590c90Snw141292 if ((s = getenv("SMF_FMRI")) == NULL || strlen(s) >= sizeof (buf)) 46271590c90Snw141292 buf[0] = '\0'; 46371590c90Snw141292 else 46471590c90Snw141292 (void) strlcpy(buf, s, sizeof (buf)); 46571590c90Snw141292 46671590c90Snw141292 membar_producer(); 46771590c90Snw141292 fmri = buf; 46871590c90Snw141292 46971590c90Snw141292 return (get_fmri()); 47071590c90Snw141292 } 47171590c90Snw141292 47271590c90Snw141292 /* 47371590c90Snw141292 * Wrappers for smf_degrade/restore_instance() 47471590c90Snw141292 * 47571590c90Snw141292 * smf_restore_instance() is too heavy duty to be calling every time we 47671590c90Snw141292 * have a successful AD name<->SID lookup. 47771590c90Snw141292 */ 47871590c90Snw141292 void 479349d5d8fSnw141292 degrade_svc(int poke_discovery, const char *reason) 48071590c90Snw141292 { 48171590c90Snw141292 const char *fmri; 48271590c90Snw141292 48371590c90Snw141292 membar_consumer(); 48471590c90Snw141292 if (degraded) 48571590c90Snw141292 return; 486349d5d8fSnw141292 487148c5f43SAlan Wright idmapdlog(LOG_ERR, "Degraded operation (%s).", reason); 488349d5d8fSnw141292 48971590c90Snw141292 membar_producer(); 490148c5f43SAlan Wright degraded = B_TRUE; 49171590c90Snw141292 49271590c90Snw141292 if ((fmri = get_fmri()) != NULL) 49371590c90Snw141292 (void) smf_degrade_instance(fmri, 0); 494c5866007SKeyur Desai 495c5866007SKeyur Desai /* 496c5866007SKeyur Desai * If the config update thread is in a state where auto-discovery could 497c5866007SKeyur Desai * be re-tried, then this will make it try it -- a sort of auto-refresh. 498c5866007SKeyur Desai */ 499c5866007SKeyur Desai if (poke_discovery) 500c5866007SKeyur Desai idmap_cfg_poke_updates(); 50171590c90Snw141292 } 50271590c90Snw141292 50371590c90Snw141292 void 50471590c90Snw141292 restore_svc(void) 50571590c90Snw141292 { 50671590c90Snw141292 const char *fmri; 50771590c90Snw141292 50871590c90Snw141292 membar_consumer(); 50971590c90Snw141292 if (!degraded) 51071590c90Snw141292 return; 51171590c90Snw141292 51271590c90Snw141292 if ((fmri = get_fmri()) == NULL) 51371590c90Snw141292 (void) smf_restore_instance(fmri); 51471590c90Snw141292 51571590c90Snw141292 membar_producer(); 516148c5f43SAlan Wright degraded = B_FALSE; 517479ac375Sdm199847 518349d5d8fSnw141292 idmapdlog(LOG_NOTICE, "Normal operation restored"); 51971590c90Snw141292 } 52071590c90Snw141292 5217a8a68f5SJulian Pullen 5227a8a68f5SJulian Pullen /* printflike */ 523c5c4113dSnw141292 void 5247a8a68f5SJulian Pullen idmapdlog(int pri, const char *format, ...) { 525*b3700b07SGordon Ross static time_t prev_ts; 526c5c4113dSnw141292 va_list args; 527*b3700b07SGordon Ross char cbuf[CBUFSIZ]; 528*b3700b07SGordon Ross time_t ts; 529*b3700b07SGordon Ross 530*b3700b07SGordon Ross ts = time(NULL); 531*b3700b07SGordon Ross if (prev_ts != ts) { 532*b3700b07SGordon Ross prev_ts = ts; 533*b3700b07SGordon Ross /* NB: cbuf has \n */ 534*b3700b07SGordon Ross (void) fprintf(stderr, "@ %s", 535*b3700b07SGordon Ross ctime_r(&ts, cbuf, sizeof (cbuf))); 536*b3700b07SGordon Ross } 537c5c4113dSnw141292 538c5c4113dSnw141292 va_start(args, format); 539c5c4113dSnw141292 (void) vfprintf(stderr, format, args); 540c5c4113dSnw141292 (void) fprintf(stderr, "\n"); 5417a8a68f5SJulian Pullen va_end(args); 54271590c90Snw141292 54371590c90Snw141292 /* 54471590c90Snw141292 * We don't want to fill up the logs with useless messages when 54571590c90Snw141292 * we're degraded, but we still want to log. 54671590c90Snw141292 */ 547148c5f43SAlan Wright if (degraded) 54871590c90Snw141292 pri = LOG_DEBUG; 54971590c90Snw141292 5507a8a68f5SJulian Pullen va_start(args, format); 5517a8a68f5SJulian Pullen vsyslog(pri, format, args); 552c5c4113dSnw141292 va_end(args); 553c5c4113dSnw141292 } 554148c5f43SAlan Wright 555148c5f43SAlan Wright static void 556148c5f43SAlan Wright trace_str(nvlist_t *entry, char *n1, char *n2, char *str) 557148c5f43SAlan Wright { 558148c5f43SAlan Wright char name[IDMAP_TRACE_NAME_MAX+1]; /* Max used is only about 11 */ 559148c5f43SAlan Wright 560148c5f43SAlan Wright (void) strlcpy(name, n1, sizeof (name)); 561148c5f43SAlan Wright if (n2 != NULL) 562148c5f43SAlan Wright (void) strlcat(name, n2, sizeof (name)); 563148c5f43SAlan Wright 564148c5f43SAlan Wright (void) nvlist_add_string(entry, name, str); 5657a8a68f5SJulian Pullen } 5667a8a68f5SJulian Pullen 567148c5f43SAlan Wright static void 568148c5f43SAlan Wright trace_int(nvlist_t *entry, char *n1, char *n2, int64_t i) 5697a8a68f5SJulian Pullen { 570148c5f43SAlan Wright char name[IDMAP_TRACE_NAME_MAX+1]; /* Max used is only about 11 */ 571148c5f43SAlan Wright 572148c5f43SAlan Wright (void) strlcpy(name, n1, sizeof (name)); 573148c5f43SAlan Wright if (n2 != NULL) 574148c5f43SAlan Wright (void) strlcat(name, n2, sizeof (name)); 575148c5f43SAlan Wright 576148c5f43SAlan Wright (void) nvlist_add_int64(entry, name, i); 5777a8a68f5SJulian Pullen } 5787a8a68f5SJulian Pullen 579148c5f43SAlan Wright static void 580148c5f43SAlan Wright trace_sid(nvlist_t *entry, char *n1, char *n2, idmap_sid *sid) 5817a8a68f5SJulian Pullen { 582148c5f43SAlan Wright char *str; 583148c5f43SAlan Wright 584148c5f43SAlan Wright (void) asprintf(&str, "%s-%u", sid->prefix, sid->rid); 585148c5f43SAlan Wright if (str == NULL) 586148c5f43SAlan Wright return; 587148c5f43SAlan Wright 588148c5f43SAlan Wright trace_str(entry, n1, n2, str); 589148c5f43SAlan Wright free(str); 5907a8a68f5SJulian Pullen } 5917a8a68f5SJulian Pullen 592148c5f43SAlan Wright static void 593148c5f43SAlan Wright trace_id(nvlist_t *entry, char *fromto, idmap_id *id, char *name, char *domain) 5947a8a68f5SJulian Pullen { 595148c5f43SAlan Wright trace_int(entry, fromto, IDMAP_TRACE_TYPE, (int64_t)id->idtype); 596148c5f43SAlan Wright if (IS_ID_SID(*id)) { 597148c5f43SAlan Wright if (name != NULL) { 598148c5f43SAlan Wright char *str; 599148c5f43SAlan Wright 600148c5f43SAlan Wright (void) asprintf(&str, "%s%s%s", name, 601148c5f43SAlan Wright domain == NULL ? "" : "@", 602148c5f43SAlan Wright domain == NULL ? "" : domain); 603148c5f43SAlan Wright if (str != NULL) { 604148c5f43SAlan Wright trace_str(entry, fromto, IDMAP_TRACE_NAME, str); 605148c5f43SAlan Wright free(str); 606148c5f43SAlan Wright } 607148c5f43SAlan Wright } 608148c5f43SAlan Wright if (id->idmap_id_u.sid.prefix != NULL) { 609148c5f43SAlan Wright trace_sid(entry, fromto, IDMAP_TRACE_SID, 610148c5f43SAlan Wright &id->idmap_id_u.sid); 611148c5f43SAlan Wright } 612148c5f43SAlan Wright } else if (IS_ID_POSIX(*id)) { 613148c5f43SAlan Wright if (name != NULL) 614148c5f43SAlan Wright trace_str(entry, fromto, IDMAP_TRACE_NAME, name); 615148c5f43SAlan Wright if (id->idmap_id_u.uid != IDMAP_SENTINEL_PID) { 616148c5f43SAlan Wright trace_int(entry, fromto, IDMAP_TRACE_UNIXID, 617148c5f43SAlan Wright (int64_t)id->idmap_id_u.uid); 618148c5f43SAlan Wright } 619148c5f43SAlan Wright } 620148c5f43SAlan Wright } 621148c5f43SAlan Wright 622148c5f43SAlan Wright /* 623148c5f43SAlan Wright * Record a trace event. TRACE() has already decided whether or not 624148c5f43SAlan Wright * tracing is required; what we do here is collect the data and send it 625148c5f43SAlan Wright * to its destination - to the trace log in the response, if 626148c5f43SAlan Wright * IDMAP_REQ_FLG_TRACE is set, and to the SMF service log, if debug/mapping 627148c5f43SAlan Wright * is greater than zero. 628148c5f43SAlan Wright */ 629148c5f43SAlan Wright int 630148c5f43SAlan Wright trace(idmap_mapping *req, idmap_id_res *res, char *fmt, ...) 631148c5f43SAlan Wright { 632148c5f43SAlan Wright va_list va; 633148c5f43SAlan Wright char *buf; 634148c5f43SAlan Wright int err; 635148c5f43SAlan Wright nvlist_t *entry; 636148c5f43SAlan Wright 637148c5f43SAlan Wright assert(req != NULL); 638148c5f43SAlan Wright assert(res != NULL); 639148c5f43SAlan Wright 640148c5f43SAlan Wright err = nvlist_alloc(&entry, NV_UNIQUE_NAME, 0); 641148c5f43SAlan Wright if (err != 0) { 642148c5f43SAlan Wright (void) fprintf(stderr, "trace nvlist_alloc(entry): %s\n", 643148c5f43SAlan Wright strerror(err)); 644148c5f43SAlan Wright return (0); 645148c5f43SAlan Wright } 646148c5f43SAlan Wright 647148c5f43SAlan Wright trace_id(entry, "from", &req->id1, req->id1name, req->id1domain); 648148c5f43SAlan Wright trace_id(entry, "to", &res->id, req->id2name, req->id2domain); 649148c5f43SAlan Wright 650148c5f43SAlan Wright if (IDMAP_ERROR(res->retcode)) { 651148c5f43SAlan Wright trace_int(entry, IDMAP_TRACE_ERROR, NULL, 652148c5f43SAlan Wright (int64_t)res->retcode); 653148c5f43SAlan Wright } 654148c5f43SAlan Wright 655148c5f43SAlan Wright va_start(va, fmt); 656148c5f43SAlan Wright (void) vasprintf(&buf, fmt, va); 657148c5f43SAlan Wright va_end(va); 658148c5f43SAlan Wright if (buf != NULL) { 659148c5f43SAlan Wright trace_str(entry, IDMAP_TRACE_MESSAGE, NULL, buf); 660148c5f43SAlan Wright free(buf); 661148c5f43SAlan Wright } 662148c5f43SAlan Wright 663148c5f43SAlan Wright if (DBG(MAPPING, 1)) 664148c5f43SAlan Wright idmap_trace_print_1(stderr, "", entry); 665148c5f43SAlan Wright 666148c5f43SAlan Wright if (req->flag & IDMAP_REQ_FLG_TRACE) { 667148c5f43SAlan Wright /* Lazily allocate the trace list */ 668148c5f43SAlan Wright if (res->info.trace == NULL) { 669148c5f43SAlan Wright err = nvlist_alloc(&res->info.trace, 0, 0); 670148c5f43SAlan Wright if (err != 0) { 671148c5f43SAlan Wright res->info.trace = NULL; /* just in case */ 672148c5f43SAlan Wright (void) fprintf(stderr, 673148c5f43SAlan Wright "trace nvlist_alloc(trace): %s\n", 674148c5f43SAlan Wright strerror(err)); 675148c5f43SAlan Wright nvlist_free(entry); 676148c5f43SAlan Wright return (0); 677148c5f43SAlan Wright } 678148c5f43SAlan Wright } 679148c5f43SAlan Wright (void) nvlist_add_nvlist(res->info.trace, "", entry); 680148c5f43SAlan Wright /* Note that entry is copied, so we must still free our copy */ 681148c5f43SAlan Wright } 682148c5f43SAlan Wright 683148c5f43SAlan Wright nvlist_free(entry); 684148c5f43SAlan Wright 685148c5f43SAlan Wright return (0); 6867a8a68f5SJulian Pullen } 687